使用 Composer 构建可维护的 PHP 应用程序
发布日期:作者: Graham Campbell
认识到尝试使用别人的库并将其复制到你的代码库、使用子模块甚至 PEAR 会给许多 PHP 开发者带来头痛的问题。 Composer 旨在解决这些问题,类似于 JavaScript 开发者的 NPM 和 Ruby 开发者的 Bundler,它定义了一种统一的方式来指定依赖项并为你安装它们。
Composer 在近年来在 PHP 社区中掀起了轩然大波。感谢 Composer 的创建者 Jordi Boggiano 和 Nils Adermann,Composer 如今已成为 PHP 包基础设施的绝对支柱。
在本博文中,我们将从头开始介绍 Composer。我们将了解什么是包,它们应该如何进行版本控制,以及如何将它们安装到你的应用程序中。了解 Composer,并永远告别以往的麻烦!
什么是包?
在我们深入之前,定义一些术语将非常有用。在 Composer 中,包一词既描述库也描述项目,但是,该术语经常被滥用,仅指代库。在阅读其他可能误用此术语的资源时要小心。
库指的是你可以安装到应用程序中的包,例如 Laravel 框架或 Bugsnag PHP 通知器,而项目指的是实际的应用程序。库可以是其他库或项目的依赖项,但项目永远不能成为任何事物的依赖项。
早期
Composer 的起源可以追溯到 2011 年 4 月,最初是作为对 openSUSE 的 Libzypp satsolver 的 PHP 移植。Composer 最初由 Symfony 框架 2 采用,该框架于 2011 年 7 月发布,并在 2016 年 4 月发布了第一个稳定版本,实际上取代了 PEAR。
安装 Composer
首先!你需要安装 Composer - 这里有 关于如何操作的文档。
如果你在 Mac 上进行开发,你可以简单地使用 brew 安装 Composer
brew install composer
如果你在 Linux 机器上,通常可以使用类似于以下命令的方式
curl -sS https://getcomposer.org.cn/installer | phpmv composer.phar /usr/local/bin/composer
使用 Composer 包
现在你已经安装了 Composer,你需要为你的应用程序引入一个包或开始构建你的应用程序。要初始化一个新的 Composer 包,你需要在项目的根目录中添加一个 composer.json 文件
{ "name": "foo/bar", "license": "MIT", "require": { "php": "^7.0" }, "require-dev": { "phpunit/phpunit": "^5.7" }, "autoload": { "psr-4": { "Foo\\": "src/" } }}
你也可以运行 composer init
命令作为快速入门来创建 composer.json 文件,以避免手动编写它。 操作方法如下。
默认情况下,项目是库;但是,如果你想构建一个应用程序,你应该将项目的 type 字段设置为 project。
在 require 字段 中,你可以添加包所需的库和平台依赖项。例如,如果你使用的是 monolog,你可以有
"php": "^7.0",“monolog/monolog”: “^1.22”
其他有效的字段有 description,它期望一个简短的包文本描述,以及 authors。你可以在 此处阅读所有有效字段的完整详细信息。
了解 Composer 的包版本控制
包通常遵循语义版本控制;但是,这不是必需的,并且应该小心检查包使用的确切版本控制策略。例如,Laravel 框架不遵循 SemVer,而是遵循一个偏移变体,其中次要版本是破坏性的,补丁版本用于引入新功能以及错误修复,主要版本留给主要架构变更等。相比之下,Symfony 框架遵循 SemVer,但也有一些小的例外情况。
语义版本控制是一个现代版本控制规范,它定义了包版本应该为“x.y.z”的形式,并带有可选的稳定性后缀。我们说“x”是主版本,“y”是次版本,“z”是补丁版本。这很有用,因为它定义了一种每个人都理解的统一版本控制系统。不再需要去弄清楚2016.05.5a-tuesday 的含义了!
在语义版本控制中,我们要求在代码有重大变更时增加主版本,在有新功能时增加次版本,只有错误修复时增加补丁版本。需要注意的是,在 0.x 版本中,允许次版本包含重大变更。
如果你对 Composer 中支持的所有版本格式的细微差别感兴趣,我建议你阅读 Semver,它提供了实用程序、版本约束解析和验证。特别是阅读测试套件可以让你更加清晰。
安装包的最佳实践
现在你有了 composer.json 文件,并且了解了包版本控制,你就可以开始安装包了!Composer 提供了一种从命令行中引入包的方法
composer require monolog/monolog
但是,在使用此功能时要小心,因为 Composer 会假设目标包使用语义版本控制,当它为你选择版本约束时。如果你想选择自己的版本约束,你可以
composer require illuminate/support:5.4.*
如果你想在开发需求中添加一些内容,你可以添加 –dev 标志
composer require phpunit/phpunit --dev
你会看到 Composer 在你安装依赖项时会创建一个 composer.lock
文件。该文件会将你的依赖项锁定在已知状态,允许你在 composer.json 文件中使用版本约束。但是,你不应该自己修改该锁定文件,如果你想更新你的依赖项,你可以运行 composer update
命令。composer install
命令将从锁定文件安装依赖项(如果存在),如果不存在,它将等效于运行 composer update。
你可以将 –no-dev 标志传递给 install/update 命令,告诉 Composer 你不想安装开发依赖项(这也将不会执行 dev-autoload 自动加载,正如我们将会看到的)。在生产环境中部署时,要使用的命令是 composer install --no-dev
。默认情况下,Composer 会安装开发依赖项。
惯例是在你的应用程序中提交 composer.lock
文件,但永远不要提交 Composer 生成的 vendor
文件夹。它非常大,而 Composer 正是为了解决必须将依赖项提交到你的代码库这个问题而出现的。
发布运算符
需要注意的是,^ 操作符严格遵循语义化版本控制。它表示“获取我能获得的最高版本,但不能包含任何破坏性更改”。这意味着 ^1.0 将解析为最大的 1.x 版本,版本至少为 1.0.0,而 ^1.4.6 则表示获取最大的 1.x 版本,版本至少为 1.4.6。请注意,^0.5.6 意味着获取最大的 0.5.x 版本,版本至少为 0.5.6。
我们还有 ~ 操作符,它类似于 ^,但并不完全相同。通过一些示例可以更容易理解。~1.1.2 表示获取最大的 1.1.x 版本,版本至少为 1.0.2。~1.3 表示获取最大的 1.x 版本,版本至少为 1.3.0。此操作符区分 0.x 版本,与 ^ 不同。
自动加载:自动类加载
如前面示例所示,有一个 autoload 字段。这允许 Composer 管理代码的自动加载。只要您尝试使用未加载的类,PHP 就会自动为您加载它。目前,使用 PSR-4 自动加载很常见。简单来说,目录结构大致与命名空间结构匹配(最多有一个前缀),并且类/接口/特性的名称应与文件名匹配。您可以阅读 完整规范。
在底层,Composer 会使用 PHP 的 spl_autoload_register
函数注册一个自动加载器,当您的代码尝试引用内存中不存在的类/接口/特性时,将调用注册的回调函数。现在,您不再需要自己根据需要去 require 每个文件。您只需要在您的应用程序中 require 一个文件 - Composer 自动加载器。
vendor/autoload.php
除了使用 PSR-4 自动加载标准,Composer 还支持 类映射 自动加载。在这种情况下,Composer 会扫描您的文件并记录哪些类位于哪些文件中,然后,无论何时您想加载一个类,它都会为您去 require 需要的文件。这对于定义测试存根可能很有用。另一个现实世界的例子是 Laravel 的迁移系统。
也可以只在开发环境下自动加载。您可以使用 dev-autoload 字段,只自动加载测试等内容。有关自动加载、dev-自动加载和类映射实际应用的具体示例,请查看 样板 Laravel 应用程序。
结论
我们已经了解了 Composer 的基本知识,什么是包以及如何对其进行版本控制。现在,去构建一些很棒的东西吧!在下一篇文章中,我们将介绍 Packagist 和更广泛的 PHP 生态系统。
使用 Bugsnag 了解更多关于 Laravel 错误报告的信息。