Composer 的版本约束可以分为 版本号约束 和 稳定性约束,两者结合共同影响着 Composer 的版本约束。
版本号从大到小排列,稳定性从 stable、RC、beta、alpha、dev 排列,先排版本号后稳定性。
排列例如:
v1.3 > v1.2.5 > v1.2.3 > v1.2.3-beta > v1.2.1 > v1.2.0-rc > v1.2.0-beta > v1.2.0-dev > v1.2.0
运算符
Composer 可以通过运算符控制包版本。
1.2.3
匹配具体版本。
>=1.0,<=1.2
范围匹配。有效的运算符有:>
、>=
、<
、<=
、!=。如果有多个范围,“,” 表示 逻辑AND,“|”表示 逻辑OR,AND 优先级高于 OR。
通配符 *
1.2.* 匹配 1.2.0(包含) 到 1.1(不包含)之间版本。
波浪号 ~
匹配 下一个重要版本。~ 1.2 匹配 1.2 到 2.0 之间版本。
幂符号 ^
匹配 最新而不产生兼容性问题的版本。
一横符号 -
匹配区间。5.2 - 5.4 匹配 5.2(包括)到 5.4(包括) 版本。
三段式版本号
大版本.小版本.补丁版本
- 如果你到软件或者库有一些 BUG 被修复了,补丁版本号 +1;
- 如果你增加了新功能,或者代码库增加了一个新方法,用户升级代码库后不会产生兼容问题,小版本号 +1;
- 如果软件完全重构,或者代码库完全重构以至于用户升级之后会产生兼容问题,大版本号 +1。
幂符号 ^ 对比 波浪号 ~
- ~ 只能改变最末尾的版本号,例如: ~1.2.3 匹配 1.2.3(包含) 到 1.3.0 。
- ^ 参考上面 三段式版本号 ,匹配到不产生兼容性问题的版本。也就是说除 大版本号 之外,小版本号 和 补丁版本号 都可以改变。
- 当 版本号 只写到 小版本号 时,~ 和 ^ 匹配相同。例如 ~1.2 和 ^1.2 均匹配 1.2.0(包含) 到 2.0.0。
大版本号以 0 开头
当 大版本号 以 0 开头,^0.3.0 匹配的是 >=0.3.0,<0.4.0。
原因
semantic versioning 规定:以 0 开头的 大版本号 表示一个 非稳定版本(unstable),处于非稳定状态下,小版本号不允许向下兼容。根据 ^ 匹配到不产生兼容性问题的版本的规则,无法改变小版本,因为改变小版本会导入兼容性问题。
⚠️ 所以 ~0.1 匹配 >=0.1,<1.0 比较危险。
😋 实践一下
根据我开头写的,先排版本号,版本号相同再排稳定性,Composer 默认会在你看出的版本控制范围之内选择安装最 “右” 版本。
实践对象
包:topthink/framework
前几个版本号:
- 6.0.x-dev
- v6.0.8
- v6.0.7
- v6.0.6
- v6.0.5
- v6.0.4
- v6.0.3
- v6.0.2
- v6.0.1
- v6.0.0
- v6.0.0-rc5
- v6.0.0-rc4
- v6.0.0-rc3
- v6.0.0-rc2
- v5.2-rc1
- v5.2-beta.3
- v5.2-beta.2
- 5.1.x-dev
- v5.1.41
版本一:5.2.*@beta
使用 5.2.*@beta 版本约束,首先 5.2.* 匹配 >=5.2.0,<5.3.0,符合约束的版本并排序为 v5.2-rc1 > v5.2-beta.3 > v5.2-beta.2 ,然后看 稳定性标签 beta,因为 rc 稳定性 大于 beta,那么第一个版本 v5.2-rc1 达到要求,Composer 会安装这个版本,而不是 v5.2.beta.2 或是 v5.2.beta.3,虽然它们和 5.2.*@beta 很像。
./composer.json has been updated
Running composer update topthink/framework
Loading composer repositories with package information
Updating dependencies
Lock file operations: 4 installs, 0 updates, 0 removals
- Locking opis/closure (3.6.2)
- Locking psr/cache (1.0.1)
- Locking psr/simple-cache (1.0.1)
- Locking topthink/framework (v5.2-rc1)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals
- Downloading topthink/framework (v5.2-rc1)
- Installing psr/simple-cache (1.0.1): Extracting archive
- Installing psr/cache (1.0.1): Extracting archive
- Installing opis/closure (3.6.2): Extracting archive
- Installing topthink/framework (v5.2-rc1): Extracting archive
版本二:~6.0@dev
先看 版本号 约束,~6.0 表示 >=6.0.0,<6.1.0,符合条件版本根据排序第一个为 6.0.x-dev,再看 稳定性标签 dev,正好 6.0.x-dev 符合要求,Composer 会从刚才的 v5.2-rc1 升级到 v6.0.x-dev。
./composer.json has been updated
Running composer update topthink/framework
Loading composer repositories with package information
Updating dependencies
Lock file operations: 5 installs, 1 update, 1 removal
- Removing opis/closure (3.6.2)
- Locking league/flysystem (1.1.3)
- Locking league/flysystem-cached-adapter (1.1.0)
- Locking league/mime-type-detection (1.7.0)
- Upgrading topthink/framework (v5.2-rc1 => 6.0.x-dev c26dfea)
- Locking topthink/think-helper (v3.1.4)
- Locking topthink/think-orm (v2.0.40)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 5 installs, 1 update, 1 removal
- Syncing topthink/framework (6.0.x-dev c26dfea) into cache
- Removing opis/closure (3.6.2)
- Installing league/mime-type-detection (1.7.0): Extracting archive
- Installing topthink/think-helper (v3.1.4): Extracting archive
- Installing topthink/think-orm (v2.0.40): Extracting archive
- Installing league/flysystem (1.1.3): Extracting archive
- Installing league/flysystem-cached-adapter (1.1.0): Extracting archive
- Removing topthink/framework (v5.2-rc1)
- Installing topthink/framework (6.0.x-dev c26dfea): Cloning c26dfea139 from cache
版本三:~6.0@rc
版本号约束 ~6.0 表示 >=6.0.0,<6.1.0,根据排序第一个是 v6.0.x-dev,但是 稳定性标签 rc 大于 dev,所以 v6.0.x-dev 版本被忽略。往回看第二个版本 v6.0.8 稳定性表标签 stable 大于 dev 符合要求,Composer 会从v6.0.x-dev 降级到 6.0.8。
./composer.json has been updated
Running composer update topthink/framework
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 1 update, 0 removals
- Downgrading topthink/framework (6.0.x-dev c26dfea => v6.0.8)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 0 installs, 1 update, 0 removals
- Syncing topthink/framework (v6.0.8) into cache
- Downgrading topthink/framework (6.0.x-dev c26dfea => v6.0.8): Checking out 4789343672 from cache
坑一:--dry-run
require 命令有一个参数 --dry-run,进行模拟而非实际安装。但是我发现 dry-run 演示安装的版本跟实际安装的版本不一样。
例如我安装了 topthink/framework,版本号 v6.0.0,执行如下命令:
php composer.phar require --dry-run topthink/framework:~6.0@dev
结果如下。可以看到模拟从当前 v6.0.0 升级到 v6.0.8,但是我添加了稳定性标签 dev,但却不是最新 6.0.x-dev
./composer.json has been updated
Running composer update topthink/framework
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 1 update, 1 removal
- Removing opis/closure (3.6.2)
- Upgrading topthink/framework (v6.0.0 => v6.0.8)
Installing dependencies from lock file (including require-dev)
Package operations: 0 installs, 1 update, 1 removal
- Removing opis/closure (3.6.2)
- Upgrading topthink/framework (v6.0.0 => v6.0.8)
当我直接 php composer.phar require topthink/framework:~6.0@dev 进行升级,可以正常升级到 6.0.x-dev
./composer.json has been updated
Running composer update topthink/framework
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 1 update, 1 removal
- Removing opis/closure (3.6.2)
- Upgrading topthink/framework (v6.0.0 => 6.0.x-dev c26dfea)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 0 installs, 1 update, 1 removal
- Syncing topthink/framework (6.0.x-dev c26dfea) into cache
- Removing opis/closure (3.6.2)
- Upgrading topthink/framework (v6.0.0 => 6.0.x-dev c26dfea): Checking out c26dfea139 from cache
坑二:~ 和 * 写一起
~6.2 就表示了 6.2.0 到 6.3,可能受到其他语言的影响,被我写成了 ~6.2.* 愣是没看出毛病,结果报错 Invalid version string "~6.0.*"
坑三:- 运算符
“-” 表示区间,但是半角状态下。其他运算符允许和版本号紧挨着,也可以空格分开;- 必须与版本号空格分开,例如:1.5.2 - 1.10。1.5.2-1.10、1.5.2 -1.10 、1.5.2- 1.10 、1.10 - 1.5.2 都是错误。
其他
Composer 提供一个在线版本控制测试网站:https://semver.mwl.be/
从左到右依次是 包名、版本号 和 稳定性标签,通过使用 运算符,网站会自动匹配并在下方标出符合约束的版本,用来学习版本控制非常好,再也不用 require 忍受国内龟速的网络了。