刘懿东
php组件
进入思维导图模式
为什么使用组件
现代的PHP较少使用庞大的框架,而是更多地使用具有互操作性的专门组件制定解决方案
以前会花时间研究某个框架的封闭生态系统,使用这个框架提供的工具。如果框架没提供所需的功能,得自己开发。大型框架很难集成第三方库,因为这些库之间没有使用相同的接口。
现在,我们不用束缚在这些框架筑起的围墙中,开发应用时,可以从不断增加的大量专用组件中选择合适的,既然已经有了guzzle/http组件,为什么还要浪费时间自己编写处理http请求和响应的库呢?
其他开发者用了无数时间创建、优化、测试专门的组件,以便让组件尽量做好一件事。如果想快速开发更好的应用,不使用这些组件而自己重新发明轮子的话,那就太傻了
组件是什么?
组件打包的代码,用于帮你解决PHP应用中某个具体的问题。我们使用组件的是不重新实现已经实现的功能,把更多时间用在是新项目的长远目标上。
严格来说,PHP组件是一系列相关的累、接口和trait,要解决某个具体问题。组件中的类、接口和trait放在同一个命名空间
区分php组件的好坏也有技巧,特征如下
作用单一
php组件的作用单一,能很好地解决一个问题。组件不是万能钥匙,不能杂而不精,要术业有专攻。组件专注于解决一个问题,而且使用简单的接口封装功能
小型
php组件小巧玲珑,只包含解决某个问题所需的最少代码。
合作
组件之间能进行合作协作,把代码放在自己的命名空间,防止与其它组件名称上冲突
测试良好
提供良好的测试和测试覆盖率
文档完善
易于安装、理解、使用,最好有README文件去说明如何安装、使用,也可以搭建个网站放上更详细信息;组件源码也应该有文档,对类、方法、属性的参数、返回值和可能的异常加上注释
组件和框架对比
我们选择框架时,要为这个框架的工具投入很多精力,框架通常会提供大量工具,可是有时却没提供我们需要的某个具体工具,遇到这种情况时,我们要寻找并集成自定义的php库,集成第三方代码到框架中是件难事,因为第三方代码和框架可能没使用相同的接口
选择框架时,我们看中的是这个框架的未来。我们相信框架的核心开发团队,认定他们会持续投入时间开发框架,确保框架的代码能跟上现代标准。可是经常需要大量时间和精力来维护
框架优点
symfony是极好的现代框架,由很多解耦的小型组件构成,这些组件放在一起组成框架,也可以在应用中单独使用
drupal 8积极向现代的php靠拢,使用php组件构建了一个现代休的内容管理平台
laravel是一个流行的出色php框架,它构建在自身的Illuminate框架库,可是laravel的组件不能轻易解耦,用于laravel之外的应用中,laravel也没使用PSR-2社区标准,而且也不遵守语义版本方案(semver.org)。
框架选择
Aura
Laravel
Symfony
Yii
Zend
使用正确的工具做正确的事
大多数现代的php框架其实只是构建在小型php组件之上的一系列约定
如果能通过php组件准确解决的小型项目,就使用组件,组件非常便于查找并使用现有的工具;组件有助于让代码保持轻量级和灵活性
如果是多个团队成员开发的大型项目,而且能从框架提供的约定、准则和结构中受益,那就使用框架。可是框架会为我们做很多决定,而且要求我们遵守特殊的约定,框架的灵活性低一些,不过较之使用一系列php组件,框架为我们提供了很多拿来即用的工具。
查找组件
可以在packagist查找,github上的awesome php列出了很多非常优秀的php组件
搜索
ckagist是php组件的杂货店,这里可以买到最好的材料
选择
如果packagist有多个符合需求的php组件,应该怎么选择?
下载数和喜欢的人数较多
有时用的人多并不表明符合自己的需求,可以靠口碑或同伴推荐
使用
composer是php组件依赖管理器,它能和packagist紧密合作,你告诉composer使用guzzlehttp/guzzle组件,composer会从packagist中获取该组件仓库地址、使用哪个版本、还能找出并下载组件的依赖组件
composer的重要很重要,因为依赖管理和自动加载是很难处理的问题,composer会为项目中所有php组件自动生成符合PSR标准的自动加载器,composer有效抽象了依赖管理和自动加载
composer大大简化了在应用中集成和使用第三方php组件的方式
使用方式
组件名称是由厂商名和包名组成,厂商名和包名用/分隔,如yiisoft/yii2,一个组件可能含有多个版本,packagist会显示组件所有可用版本
组件名称
每个php组件的名称都由厂商名和包名组成
厂商名是全局唯一的,用于识别名下的包属于谁
包名用于唯一识别厂商名下的某个包
composer和packagist都使用vendor/package命名构定,避免不同厂商的php组件有名称冲突
语言版本
组件都使用语义化版本方案(https://semver.org/lang/zh-CN/),版本号由三个点和数字构成(如1.0.1),版本格式:主版本号.次版本号.修订号
我们可以不用找出每个组件最新稳定版的版本号,composer会代我们操作
分类
主版本号:当你做了不兼容的 API 修改,如组件的更新破坏了向后兼容性,会提升主版本号;
次版本号:当你做了向下兼容的功能性新增,小幅更新了功能,而且没破坏向后兼容性,会提升次版本号;
修订号:当你修正了向下兼容的问题或缺陷,会提升修订版本号。
compose require vendor/package
这个命令让composer查找并安装指定php组件的最新稳定版
也能让composer把组件更新到下一个主版本之前的最新版
执行这个命令后会新建或更新composer.json文件,还会创建composer.lock文件,这两个文件都要纳入版本控制系统
如果需要使用guzzlehttp/guzzle组件,只需要在执行命令
composer require guzzlehttp/guzzle
上述命令让composer把这两个组件下载到项目vendor目录里,还会创建composer.json和composer.lock文件
composer.lock文件
composer安装项目依赖后,会创建composer.lock文件,这个文件列出项目使用的所有php组件,以及组件的具体版本号,是锁定了项目,让项目只能使用具体版本的php组件
如果有composer.lock文件,composer会下载这个文件中列出的具体版本号,而不管packagist中可用的最新版本是多少,应该把composer.lock放入版本控制中,然后分发给团队成员让他们使用的php组件版本和你一样,能尽量降低由组件版本差异导致产生bug的风险
自动加载php组件
composer下载php组件时会为项目的所有依赖创建一个符合PSR标准的自动加载器,我们只需在文件最开始用require函数把composer的自动加载器包含进来就可以
require 'vendor/autoload.php';
composer下载各个php组件时会检查每个组件的composer.json文件,确定如何使用该组件,得到这个信息后,composer会在本地为该组件创建一个符合PSR标准的自动加载器,这样我们就能用自动加载器使用所有的php组件
创建php组件
创建php组件是把工作成果分享给php社区的好方式
厂商名和名包
厂商名和包名都使用小写字母
厂商名要能最大限度地表明你的身份或者组件的品牌
选择厂商名之前在packagist中搜索,确保其他开发者没使用这个名称
包名用于识别指定厂商名下的php组件,一个厂商名下可以有多个组件
命名空间
每个组件使用各自的命名空间,以防搅乱全局命名空间
人们误以为,组件的命名空间必须与组件的厂商名和包名一致,其实不然,组件使用的命名空间与组件的厂商名和包名无关
厂商名和包名只是为了packagist和composer识别组件,组件的命名空间是为了在php代码中使用组件
文件系统的组织方式
src
包含组件的源码
tests
组件的测试用例
composer.json
composer配置文件,用于描述组件,告诉composer的自动加载器,把组件中符合PSR-4规范的命名空间对应到src目录
README.md
提供关于组件的有用信息的markdown文件,如名称、说明、作者、用法、贡献指导方针、软件许可证、感谢的人
CONTRIBUTING.md
说明别人如何为这个组件做贡献的markdown文件
LICENSE
软件许可证
CHANGELOG.md
每个版本中引入的改动markdown文件
创建组件时遇到问题,可以看一下PHP League优秀的组件样板仓库(https://github.com/thephpleague/skeleton)
composer.json
必须有的文件,而且这个文件的内容必须是有效的json,composer会使用这个文件中的信息查找、安装和自动加载php组件
name
组件的厂商名和包名,二者用/分隔,这个属性的值会在packagist显示
description
简要说明组件,这个值也会在packagist中显示
keywords
几个描述组件的关键字,用于帮助别人在packagist中找到这个组件
homepage
组件网站的url
licence
采用的软件许可证,常用MIT Public License。记住,发布代码时一定要使用许可证。
authors
是一个数组,包含项目中每个作者的信息,每个作者至少包含姓名和网站url
supports
获取技术支持的方式,可以设为email或支持讨论组的url
require
列出组件自身依赖的组件,可列出每个依赖的厂商名和包名,以及最小版本号
require-dev
与require类似,不过列出的是开发这个组件所需的依赖,例如通常会把phpunit当做开发依赖
suggest
建议安装的组件,以防与其他组件合作时需要,这个字段的值是自由的文本字段,用于描述每个建议安装的组件,composer不会安装这些组件
autoload
告诉composer如何自动加载这个组件,建议使用符合PSR-4规范的自动加载器
完整格式参见https://getcomposer.org/doc/04-schema.md
README文件
这个文件通常是用户最先阅读的文件,对托管在github或bitbucket中的组件来说更是如此。因此这个文件至少提供以下信息
组件的名称和描述
安装说明
用法说明
测试说明
贡献方式说明
支持资源
作者信息
软件许可证
github或bitbucket都可使用mardown格式演染,因此我们可以使用标题、列表、链接和图像编写格式良好的README文件
实现组件
组件中所有类、接口和trait要保存在src目录中,而且都要放在composer.json文件中设定的命名空间前缀名下
版本控制
把组件提交到packagist之前,必须把组件发布到公开的代码仓库中,只要是公开的git仓库都行
最好使用语义版本方案为组件的每个版本创建标签,以便组件的使用者使用组件的某个具体版本(例如~1.2)
提交到packagist
把组件信息提交到packagist中,packagist会从组件的composer.json中获取组件的名称、描述、关键字、依赖和建议,还会发现显示了仓库的分支和标签,把仓库的标签和语言版本号对应起来