现代PHP编程指导
新时代的PHP
网上有成千上万的PHP教程,其中大多数都已经过时了,展示的是陈旧的实践方式。PHP开发者较少依赖于庞大的框架了,更多的是使用专门的小型组件。
必须要在项目中使用的特性
命名空间
命名空间是现代PHP标准的基础。现代的PHP组件和框架都放在各自全局唯一的厂商命名空间中,以免与其它厂商使用的常见类名冲突。厂商命名空间是最顶层命名空间。大多数的PHP组件为了兼容广泛使用的PSR-4自动加载器标准,会把子命名空间放到文件系统的子目录中。在为项目编写PHP组件或类时,要确保这些代码能和项目的第三方依赖在一起使用。厂商命名空间是最重要的命名空间。厂商命名空间是最顶层命名空间,用于识别品牌或所属组织,必须具有全局唯一性。一个文件要只定义一个类。
自动加载
命名空间还为PHP Framework Interop Group (PHP-FIG)制定的PSR-4自动加载器标准奠定了坚实基础。大多数现代的PHP组件都使用了这种自动加载器模式,使用依赖管理器Composer,可以自动加载项目的依赖。如果没有命名空间,不可能出现现代的PHP生态系统和基于组件的新兴架构。
使用接口
学会如何使用接口(Interface)可以轻易地把第三方PHP组件集成到自己的应用中。接口非常重要,我们应该了解,并在日常开发中使用。
接口是两个PHP对象之间的契约,其目的不是让一个对象依赖另一个对象的身份,而是依赖另一个对象的能力。接口把我们的代码和依赖解耦了,而且允许我们的代码依赖任何实现了预期接口的第三方代码。我们不管第三方代码是如何实现接口的,只关心第三方代码是否实现了指定的接口。使用接口编写的代码更灵活,能委托别人实现细节。
标准(PHP-FIG)
旧的PHP框架是单独开发的,不能与其它PHP框架共享代码。PHP框架必须使用一种通用方式,让框架之间能通信,能共享代码,也就是说,我们需要一个标准。PHP-FIG制定了推荐规范,PHP框架可以自愿实现这些规范,改进与其他框架的通信和共享功能。
框架的互操作性
PHP-FIG的使命是实现框架的互操作性。框架的互操作性是指,通过接口、自动加载机制和标准的风格,让框架相互合作。
接口
PHP框架之间通过共用的接口合作。框架通过PHP接口假定第三方依赖提供了什么方法、而不关心依赖是如何实现接口的。
自动加载
PHP框架之间通过自动加载机制合作。PHP命名空间和类必须遵守PSR-4自动加载器标准。得益于PSR-4,我们只需要使用一个自动加载器就能自动加载应用中的所有PHP组件。大多数现代的PHP组件和框架都符合PSR-4规范。如果你自己编写并分发组件,确保你的组件也符合PSR-4规范。
风格
PHP框架之间通过标准的代码风格合作。
PSR
PSR是PHP Standards Recommendation(PHP推荐标准)的简称。这些都是PHP-FIG制定的推荐规范。
PSR由4个基本推荐规范分别是:
PSR-1:基本的代码风格,PSR-2:严格的代码风格,PSR-3:日志记录器接口,PSR-4自动加载。注意,这些PHP-FIG推荐规范与我们前面提到的三种实现互操作性的方法(接口、自动加载 、和代码风格)是一一对应的。
PSR标准的官方网站是http://www.php-fig.org/,中文网址是http://phpfig.p2hp.com/。
如果想编写符合社区标准的PHP代码,首先要遵守PSR-1.这是最容易遵守的PHP标准。
写PHP程序时至少要遵循 PSR-1,PSR-4规范,能遵循PSR-2更好。
PSR-4 自动加载器策略依赖PHP命名空间和文件系统目录结构查找并加载PHP类、接口和性状。PSR-4的精髓是把命名空间的前缀和文件系统的目录对应起来。
PSR-4会把命名空间的前缀和文件系统中的目录对应起来。命名空间的前缀可以是顶层命名空间,也可以是顶层命名空间加上任意一个子命名空间,相当灵活。我们 可以使用依赖管理器Composer自动生成PSR-4自动加载器。
在PSR-4属性中,我们要把组件和命名空间前缀与相对组件根目录的文件系统路径对应起来。这样我们的组件就符合PSR-4自动加载器标准了。例如
"autoload":{
"psr-4":{
"Oreilly\\ModernPHP\\":"scr/"
}
}
把Oreilly\ModernPHP命名空间与src/目录对应了起来。在这个示例中,如果实例化Oreilly\ModernPHP\Url\Scanner类,Composer会自动加载src/Url/Scannner.php文件。
添加 autoload
字段后,你应该再次运行 install
命令来生成 vendor/autoload.php
文件。
更多请参考http://composer.p2hp.com/doc/01-basic-usage.html#--8
除了 PSR-4 自动加载,classmap 也是支持的。这允许类被自动加载,即使不符合 PSR-0 规范。详细请查看 自动加载-参考。
有些工具能根据PHP标准,帮你审核并格式化代码,例如PHP Code Sniffer(也叫phpcs),这个工具(可以直接在命令行中使用,也可以集成到IDE中使用)能指出你的代码和指定PHP代码标准之间的差异。你还可以使用PHP-CS-Fixer 自动纠正大多数不符合标准的代码。
组件
现代的PHP较少使用庞大的框架,而是更多地使用具有互操作性的专门组件制定解决方案。
组件是什么
组件是打包的代码,用于帮你解决PHP应用中某个具体的问题。我们使用组件为的是不重新实现已经实现的功能,把更多时间用在实现项目的长远目标上。PHP组件是一系列相关的类、接口和性状,用于解决某个具体问题。组件中的类、接口和性状通常放在同一个命名空间中。
好的PHP组件具有以下特征:
作用单一,小型,合作,测试良好,文档完善。
组件和框架对比
我们应该使用由组件组成的框架。我们应该使用组件还是框架呢?答案是,使用正确的工具做正确的事。大多数现代的PHP框架其实只是构建在小型PHP组件之上的一系列约定。
如果是能通过一些PHP组件准确解决问题的小型项目,那就使用组件。组件非常便于查找并使用现有的工具,还有助于让代码保持轻量级和灵活性。
如果是有多个团队成员开发的大型项目,而且能从框架提供的约定、准则和结构中受益,那就使用框架。使用框架能引导并加速项目的开发。
组件的名称
每个PHP组件的名称都由厂商名和包名组成。例如,对流行的league/flysystem组件来说,厂商名是league,包名是flysystem.厂商名和包名之间由/符号分隔。厂商名和包名在一起组成完整的组件名league/flysystem。厂商名是全局唯一的,这是全局标识符,用于识别名下的包属于谁。包名用于唯一识别指定厂商名下的某个包。Composer和Packagist都使用vendor/package这种命名约定。我建议厂商名和包名都只使用小写字母。
查找组件
我们可以在PHP组件目录Packagist(http://packagist.p2hp.com/)中查找现代PHP组件。另外Awesome PHP(https://github.com/ziadoz/awesome-php)列出的PHP组件是最好的。
Composer
Composer(http://composer.p2hp.com/)是安装PHP组件的工具。Composer是PHP组件的依赖管理器,运行在命令行中。你告诉Composer需要哪些PHP组件,Composer会下载并把这些组件自动加载到你的项目中。Composer能和Packagist紧密合作。Composer有效抽象了依赖管理和自动加载。
我认为对PHP社区来说,Composer是最重要的附加工具。Composer改变了我创建PHP应用的方式。它能大大简化在应用中集成和使用第三方PHP组件的方式。
composer.json和composer.lock文件都要纳入版本控制系统。
composer.lock文件会列出项目使用的所有PHP组件,以及组件的具体版本号。这其实是锁定了项目,让项目只能使用具体版本的PHP组件。
创建PHP组件
命名空间
人们经常误以为,组件的命名空间必须与组件的厂商名和包名一致。其实不然,组件使用的命名空间与组件的厂商名和包名无关。厂商名和包名只是为了让Packagist和Composer识别组件。而组件的命名空间是为了在PHP代码中使用组件。
文件系统的组织方式
PHP组件的文件系统结构基本上是定型的:
src/ 这个目录包含组件的源码
tests/ 这个目录包含组件的测试。
composer.json 这个是Composer配置文件。
README.md 这个markdown文件提供关于组件的有用信息,包括组件的名称、说明、作者、用法、贡献者指导方针、软件许可证和要感谢的人。
CONTRIBUTING.md 这个markdown文件说明别人如何为这个组件做贡献。
LICENSE 这个纯文本文件包含组件的软件许可证。
CHANGELOG.md 这个markdown文件列出组件在每个版本中引入的改动。
提示:如果创建PHP组件时遇到问题,可以看一下PHP League优秀的组件样板仓库(https://github.com/thephpleague/skeleton)。
composer.json文件
PHP组件中必须有composer.json文件,而且这个文件的内容必须是有效的JSON,Composer会使用这个文件中的信息查找 、安装和自动加载 PHP组件。composer.json文件还包含组件在Packagist目录中的信息。
README文件
README文件至少要提供以下信息:
组件的名称和描述、安装说明、用法说明、测试说明、贡献方式说明、支持资源、作者信息、软件许可证。
提交到Packagist
现在可以把组件提交到Packagist了。如果你不使用GitHub,先去注册一个Packagist帐号。如果使用GitHub,也可以使用GitHub的凭据登录Packagist.我们可以在GitHub中创建一个钩子,每次更新组件的仓库时通知Packagist。在仓库中设置钩子的方法参阅https://Packagist.org/profile/。
使用这个组件
使用Composer安装这个组件,在终端下执行下面的命令
composer require modernphp/scanner
然后可以像下面这样使用这个组件
<?php
require 'vendor/autoload.php';
$urls=[
'http://www.baidu.com',
'http://www.php.net',
'http://www.apple.com'
];
$scanner= new \Oreilly\ModernPHP\Url\scanner($urls);
print_r($scanner->gitInvalidUrls());
参考《Modern PHP》
转载请注明来自Lenix的博客,网址http://blog.p2hp.com/archives/3634 。
最后更新于 2020年11月8日