composer 指令集和项目配置文件解析
查看版本号
composer -V[--version]
require 关键词
第一个(并且经常唯一一个)你需要在 composer.json
配置文件中明确规定的东西就是 require
关键词。配置文件列出项目的依赖包和和可能包含的元数据。
{
"require": {
"monolog/monolog": "1.0.*"
}
}
正如你看到的,require
携带一个映射依赖包名称到版本限定(比如 1.0.*
)的对象。
composer 使用这个信息在你使用 repositories
关键词注册的依赖包仓库或者在默认的依赖包仓库 Packagist 去搜索准确的文件集合。在上面的例子中,既然在 composer.json
中没有已经注册其他的仓库,就会默认 monolog/monolog
依赖包是注册在 Packagist 中的。
[notice] 关于 Packagist 和 repositories 仓库的概念可以点击 packagist 和 repos 查看。[/notice]
包名
包名由一个 vendor 名和项目名组成。经常出现会项目名相同的情况,而 vendor 名存在的目的就是防止命名冲突。举个例子,两个不同的人都可以创建一个叫 json
的库。一个可能会叫 igorw/json
,另一个可能叫 seldaek/json
。
阅读更多有关发布包和包命名规则可以看这里。(注意,你也可以将 “平台包” 定义为依赖包,这样你可以依赖某些服务软件版本,查看更多关于“平台包”)
包版本限定
在我们的例子中,我们将请求版本限定为 1.0.*
的 Monolog 包。这表示任何 1.0
开发分支,或者大于等于 1.0 并小于 1.1 的任何版本(>=1.0 <1.1
)。
请阅读 版本 了解更多关于版本,版本之间如何互相关联和关于版本限定的深入详细的信息。
[notice]
composer 是如何下载正确的文件的?当你在 composer.json
中明确规定一个依赖的时候,composer 首先你之前请求过的包名并在你使用 repositories
注册的所有仓库中搜索。如果你还没有注册过任何的仓库,或者它没有找到你所明确规定的包名,它会回撤到 Packagist。
[/notice]
[notice]
当 composer 找到了正确的包,不管是在 Packagist 中还是在一个你定义的仓库中,它接着会利用包的版本控制系统(VCS)的版本特征(比如,分支或者是标记)尝试找到与你定义的版本限定最匹配的版本。一定要阅读版本和包解决方案的版本文章。
[/notice]
[notice]
注意:当你尝试引入一个包但 composer 抛出关于包稳定性的错误,这说明你规定的包版本没有满足你默认的最低稳定性的要求。在你的 VCS 中搜索有效包版本的时,默认只考虑稳定的发布版。
[/notice]
安装依赖
为了给你的项目安装定义的依赖,执行 install
指令。
php composer.phar install
[or directly] composer install
当你执行这个指令时,会发生两件事:
- 不存在
composer.lock
时的安装
如果你之前从来没有执行过这个指令并且现在没有 composer.lock
文件,composer 会简单解析所有你在 composer.json
文件中列出的依赖,并下载这些依赖文件的最新版本到你项目下的 vendor 目录下(vendor 目录是一个项目中第三方代码按照惯例存放的位置)。在我们上面的例子中,最终会以 vendor/monolog/monolog/
下的 Monolog 源代码结束。如果 Monolog 列出任何的依赖,这些依赖也会被放在 vendor
下的文件夹中。
[notice]提示:如果你的项目使用 git,那么很有可能你会想把 vendor
添加到 .gitignore
中。你肯定不会想要把所有第三方代码添加到你的版本仓库中的。[/notice]
当 composer 结束安装之后,它会写入下载的所有包和包具体的版本到 composer.lock
文件中,锁定项目依赖到这些具体的版本。你应该把 composer.lock
文件提交到你的项目仓库中,这样所有在这个项目中工作的人但会锁定相同版本的依赖。
- 存在
composer.lock
时的安装
这把我们带到第二个场景。如果当你运行 composer install
的是时候 composer.lock
以及 composer.json
已经存在,它意味着或者你之前执行过 install
指令,或者项目中的其他某个人执行过 install
指令,并且将 composer.lock
提交到项目中(这是好的)。
不管哪种情况,在 composer.lock
已存在时执行 install
指令会解析并安装所有你在 composer.json
中列出的依赖,但 composer 会使用 composer.lock
中列出的精确版本来确保项目中所有人拿到的包版本是一直的。最终你会得到所有在 composer.json
中请求的依赖,但他们可能不会是最新可获得的版本(有些在 composer.lock
中列出的依赖子文件创建后可能已经发布了更新的版本)。这是故意的,这能确保你的项目不会因为依赖上发生的未知变化而挂掉。
- 提交
composer.lock
到版本控制
提交 composer.lock
到版本控制很重要,这会使得任何创建项目的人使用和你一样的依赖。你的 CI 服务器(持续集成服务器),生产机器,你团队中其他的开发者,所有东西和所有的人运行相同的依赖,这会减少出现只影响到部分部署的 bugs 的可能性。即使你单独开发,在 6 个月后重新安装项目,你可以很自信依赖安装任然有效,即使自那以后你的依赖包发布了很多个新版本。(查看下面关于 update
指令的注意点。)
更新依赖到他们最新的版本
就像上面提到的,composer.lock
文件防止你自动获取到你的依赖包的最新版本。为了更新到最新的版本,使用 update
指令。它可以取回最新适配的版本(根据你的 composer.json
文件)并使用最新版本更新锁文件。(这相当于是删除了 composer.lock
文件再执行一次 install
指令。)
php composer.phar update
[notice]注意:如果 composer.json
发生了可能会影响到依赖解决的改变后,composer.lock
一直没有更新的话,在执行 install
指令时会展示一个警告[/notice]
如果你只想安装或更新一个依赖,可以把它添加到白名单列表
php composer.phar update monolog/monolog [...]
[notice]注意:对于库文件没有必要更新 composer.lock
文件,具体查看 Libraries - Lock file[/notice]
Packagist
Packagist 是主要的 composer 仓库。一个 composer 仓库基本就是一个包源:一个你可以获取到依赖包的地方。Packagist 旨在成为所有人使用的中央仓库。这意味着你可以自动 require
依赖那里可获得的任何包,而不需要进一步明确规定 composer 寻找包的地方。
如果你去 Packagist 网站 (packagist.org),你可以浏览和搜索包。
任何使用 composer 的开源项目都建议发布他们的包到 Packagist 上。一个库(library )不需要放到 Packagist 来让 composer 使用,但这样做会让其他开发者更快的找到和采用。
平台包(Platform packages)
composer 有平台包,相比安装再系统中但不是通过 composer 安装的东西,平台包是虚拟的包。这包括 PHP 本身,PHP 扩展和一些系统类库。
php
代表用户的 php 版本,允许你使用一些限定,比如说版本^7.1
。规定 64 bit 位版本的 php,你可以规定php-64bit
的包。hhvm
代表 HHVM 运行态的版本,并且允许你使用一个限定,比如^2.3
。- ext-
允许你规定 PHP 扩展(包括核心扩展)。这里的版本可以完全不同,所以通常设置限制为 *
比较好。举个扩展包的例子:ext-gd
。 - lib-
允许在 PHP 使用的库版本上做一些限定。这些都是可获取到的: curl
,iconv
,icu
,libxml
,openssl
,pcre
,uuid
,xsl
。
你可以使用 show --platform
来得到一个你本地可获取到的平台包列表。
自动加载(Autoloading)
对于明确定义自动信息的类库,Composer 生成一个 vendor/autoload.php
文件。你可以简单引入(include)这个文件并开始使用那些类库提供的类,而不需要额外操作。
require __DIR__ . '/vendor/autoload.php';
$log = new Monolog\Logger('name');
$log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING));
$log->addWarning('Foo');
你甚至可以通过在 composer.json
添加一个 autoload
定义域来添加自己代码到自动加载器中。
{
"autoload": {
"psr-4": {"Acme\\": "src/"}
}
}
Composer 会给 Acme
命名空间注册一个 [PSR-4][10]
自动加载器。
你可以定义一个从命名空间到目录的映射关系。src
目录应该是在你的根目录,跟 vendor
目录所在是同一级。举个例子,文件名可以是包含 Acme\Foo
类的 src/Foo.php
。
在添加 autoload
定义域之后,你得重新运行一次指令:
php composer.phar dump-autoload
这个指令会重新生成一个 vendor/autoload.php
文件。查看 dump-autoload 小节获取更多信息。
引入那个文件还会返回一个自动加载器(autoloader)实例,这样你就可以在一个变量中存储引入调用的返回值并添加更多的命名空间。这对于在测试套件中自动加载类会很有帮助,比如说:
$loader = require __DIR__ . '/vendor/autoload.php';
$loader->addPsr4('Acme\\Test\\', __DIR__);
除了 PSR-4 的自动加载,Composer 还提供 PSR-0, classmap 和 files 的自动加载。查看 autoload 指南获取更多信息。
也可以在 optimizing the autoloader 查看文档。
[notice]Composer 提供自己的自动加载器。如果你不想用那一个,你可以引入 vendor/composer/autoload_*.php
文件,这个文件会返回让你配置自己的自动加载器的关联数组。[/notice]