版本与约束
Composer版本 vs VCS版本
由于 Composer 大量使用像 git 这样的版本控制系统,"版本"这个术语可能会有些模糊。在版本控制系统的意义上,"版本"是一组包含特定数据的特定文件。在 git 术语中,这被称为 "ref",或一个特定的提交,它可能由分支 HEAD 或标签表示。当你在 VCS 中签出该版本时——例如,标签 v1.1 或提交 e35fa0d —— 你是在请求一组已知的文件,并且总是会得到相同的文件。
在 Composer 中,通常被随意称为版本的内容——即 require 行中包名后面的字符串(例如 ~1.1 或 1.2.*)——实际上更具体地说是一个版本约束。Composer 使用版本约束来确定它应该在 VCS 中签出哪些 refs(或者在静态维护的库中验证给定库是否可接受,该库在 composer.json 中有 version 规范)。
VCS 标签和分支
对于接下来的讨论,我们假设有一个如下的示例库仓库:
~/my-library$ git branchv1
v2
my-feature
another-feature~/my-library$ git tagv1.0
v1.0.1
v1.0.2
v1.1-BETA
v1.1-RC1
v1.1-RC2
v1.1
v1.1.1
v2.0-BETA
v2.0-RC1
v2.0
v2.0.1
v2.0.2标签
通常情况下,Composer 处理的是标签(而不是分支——如果你不知道这是什么意思,可以阅读一下 版本控制系统 的相关资料)。
当你编写版本约束时,它可能引用一个特定的标签(例如 1.1),也可能引用一个有效的标签范围(例如 >=1.1 <2.0,或 ~4.0)。为了解析这些约束,Composer 首先会要求 VCS 列出所有可用的标签,然后根据这些标签创建一个内部的可用版本列表。在上面的例子中,Composer 的内部列表包括版本 1.0、1.0.1、1.0.2、1.1 的 beta 版本、1.1 的第一个和第二个候选发布版本(即RC)、1.1 的最终发布版本等等。(注意 Composer 会自动移除实际标签名中的 'v' 前缀,以获得有效的最终版本号。)
当 Composer 从你的 VCS 中获得了完整的可用版本列表后,它会找到符合项目中所有版本约束的最高版本(其他包可能需要该库的更具体版本,所以选择的版本不一定总是最高的可用版本),然后下载该标签的 zip 存档并解压到 vendor 目录中的正确位置。
分支
如果你想让 Composer 签出分支而不是标签,你需要使用特殊的 dev-* 前缀(有时是后缀;见下文)指向该分支。如果你正在签出分支,则假定你想要在该分支上进行工作,Composer 实际上会将仓库克隆到你的 vendor 目录中的正确位置。而对于标签,它只是复制正确的文件而不会真正克隆仓库。(你可以通过 --prefer-source 和 --prefer-dist 修改此行为,参见 安装选项。)
在上述例子中,如果你想签出 my-feature 分支,你需要在 require 子句中指定 dev-my-feature 作为版本约束。这将导致 Composer 将 my-library 仓库克隆到我的 vendor 目录中并签出 my-feature 分支。
当分支名称看起来像版本时,我们必须向 Composer 明确表示我们试图签出分支而不是标签。在上述例子中,我们有两个版本分支:v1 和 v2。为了让 Composer 签出这些分支之一,你必须指定类似这样的版本约束:v1.x-dev。其中 .x 是一个任意字符串,Composer 需要它来告诉我们谈论的是 v1 分支而不是 v1 标签(或者,你可以将分支命名为 v1.x 而不是 v1)。对于具有版本样名称的分支(在此例中为v1),你应附加 -dev 作为后缀,而不是使用 dev- 作为前缀。
稳定性
Composer 识别以下稳定性级别(按稳定性从小到大顺序排列):dev、alpha、beta、RC 和 stable,其中 RC 代表发布候选版本。版本的稳定性由其后缀定义,例如版本 v1.1-BETA 的稳定性为 beta,v1.1-RC1 的稳定性为 RC。如果缺少此类后缀,例如版本 v1.1,则 Composer 认为该版本是 stable。此外,Composer 会自动为所有数字分支添加 -dev 后缀,并为从 VCS 仓库导入的所有其他分支添加 dev- 前缀。在这两种情况下,都会分配 dev 稳定性。
记住这一点将在下一节中对你有所帮助。
最低稳定性
还有一个因素会影响从库的 VCS 中签出哪些文件并添加到你的项目中:Composer 允许你指定稳定性约束来限制哪些标签被视为有效。在上述例子中,注意该库在正式发布 1.1 版本之前发布了 beta 版本和两个发布候选版本。为了在运行 composer install 或 composer update 时接收这些版本,我们必须明确告诉 Composer 我们可以接受发布候选版本和 beta 发布版本(如果我们想要的话,也包括 alpha 发布版本)。这可以通过在 composer.json 中设置项目范围的 minimum-stability 值,或在版本约束中使用"稳定性标志"来完成。更多详情请参阅 schema 页面。
编写版本约束
现在你已经了解了 Composer 如何看待版本,让我们来谈谈如何为你的项目依赖项指定版本约束。
精确版本约束
你可以指定包的确切版本。这会告诉 Composer 只安装这个版本。如果其他依赖项需要不同的版本,求解器最终会失败并中止任何安装或更新过程。
示例:1.0.2
版本范围
通过使用比较运算符,你可以指定有效版本的范围。有效的运算符有 >, >=, <, <=, !=。
你可以定义多个范围。用空格( )或英文逗号(,)分隔的范围将被视为逻辑与。双管道符(||)将被视为逻辑或。与(AND)的优先级高于或(OR)。
注意
使用无界范围时要小心,因为你可能会意外安装破坏向后兼容性的版本。为了安全起见,考虑使用 caret(插入/脱字) 运算符。
注意
在较旧版本的 Composer 中,单管道符(|)是逻辑或的推荐替代方案。因此为了向后兼容,单管道符(|)仍将被视为逻辑或。
示例:
>=1.0>=1.0 <2.0>=1.0 <1.1 || >=1.2
连字符版本范围(-)
包含的一组版本集合。右侧的部分版本会用通配符补全。例如 1.0 - 2.0 等同于 >=1.0.0 <2.1,因为 2.0 会变成 2.0.*。另一方面,1.0.0 - 2.1.0 等同于 >=1.0.0 <=2.1.0。
示例:1.0 - 2.0
通配符版本范围(.*)
你可以用 * 通配符指定一个模式。1.0.* 等同于 >=1.0 <1.1。
示例:1.0.*
下一个重要发布操作符
波浪号版本范围 (~)
~ 操作符最好通过示例来解释:~1.2 等同于 >=1.2 <2.0.0,而 ~1.2.3 等同于 >=1.2.3 <1.3.0。如你所见,这对于遵循 语义化版本控制 的项目非常有用。常见的用法是标记你所依赖的最小次版本,如 ~1.2(允许任何版本直到 2.0,但不包括 2.0)。理论上在 2.0 之前应该没有向后兼容性破坏,所以这样很有效。另一种理解方式是使用 ~ 指定了最小版本,但允许指定的最后一位数字增加。
示例:~1.2
注意
尽管 2.0-beta.1 严格来说在 2.0 之前,但像 ~1.2 这样的版本约束不会安装它。如上所述,~1.2 只意味着后面 .2 可以改变,但前面 1. 部分是固定的。
注意
~ 操作符在主版本号方面有一个例外行为。这意味着例如 ~1 和 ~1.0 是相同的,因为它不会允许主版本号增加以保持向后兼容性。
插入符号版本范围 (^)
^ 操作符行为非常相似,但它更贴近语义化版本控制,并且总是允许非破坏性更新。例如 ^1.2.3 等同于 >=1.2.3 <2.0.0,因为在 2.0 之前的任何发布版本都不应该破坏向后兼容性。对于 1.0 之前的版本,它也会出于安全考虑,将 ^0.3 视为 >=0.3.0 <0.4.0,将^0.0.3 视为 >=0.0.3 <0.0.4。
这是编写库代码时推荐使用的操作符,以实现最大的互操作性。
示例:^1.2.3
注意
如果你在 Windows 上使用 PowerShell,你需要在 CLI 中使用插入符号作为参数时进行转义,例如使用 composer require 命令时。你需要使用四个连续的插入符号操作符,例如 ^^^^1.2.3,以确保插入符号操作符能正确传递给 Composer。
稳定性约束
如果你使用的约束没有明确定义稳定性,Composer 将根据使用的运算符在内部默认为 -dev 或 -stable。这个过程是透明的。
如果你希望在比较中只明确考虑稳定版本,可以添加后缀 -stable。
示例:
| 约束条件 | 内部表示 |
|---|---|
1.2.3 | =1.2.3.0-stable |
>1.2 | >1.2.0.0-stable |
>=1.2 | >=1.2.0.0-dev |
>=1.2-stable | >=1.2.0.0-stable |
<1.3 | <1.3.0.0-dev |
<=1.3 | <=1.3.0.0-stable |
1 - 2 | >=1.0.0.0-dev <3.0.0.0-dev |
~1.3 | >=1.3.0.0-dev <2.0.0.0-dev |
1.4.* | >=1.4.0.0-dev <1.5.0.0-dev |
然而,为了在约束级别不强制执行各种稳定性,你可以使用 stability-flags 如 @<stability>(例如 @dev)来让 Composer 知道给定的包可以安装在与默认最低稳定性设置不同的稳定性级别上。所有可用的稳定性标志都在 schema 页面
总结
"require": {
"vendor/package": "1.3.2", // 精确指定 1.3.2 版本
// >, <, >=, <= | 指定上限/下限
"vendor/package": ">=1.3.2", // 大于或等于 1.3.2 的任何版本
"vendor/package": "<1.3.2", // 小于 1.3.2 的任何版本
// * | 通配符
"vendor/package": "1.3.*", // >=1.3.0 <1.4.0
// ~ | 允许指定的最后一位数字增加
"vendor/package": "~1.3.2", // >=1.3.2 <1.4.0
"vendor/package": "~1.3", // >=1.3.0 <2.0.0
// ^ | 不允许破坏性变更(主版本号固定 - 遵循语义化版本控制)
"vendor/package": "^1.3.2", // >=1.3.2 <2.0.0
"vendor/package": "^0.3.2", // >=0.3.2 <0.4.0 // 除非主版本号为 0
}测试版本约束
你可以使用 semver.madewithlove.com 测试版本约束。
填写包名,Composer会自动将它填充添加到你的 composer.json 文件中的默认版本约束。你可以调整版本约束,该工具将高亮显示所有匹配的发布版本。








