必须在 require 中写 "php": "^8.1",这是唯一触发安装时硬性校验的位置;config.platform.php 仅模拟环境用于依赖解析,不构成运行门槛,且需完整版本号如 "8.0.30" 才生效。

核心结论很明确:必须在 require 字段下声明 "php": ">=8.1.0"。这是 Composer 进行最低版本硬性校验的唯一入口。如果只依赖 config.platform.php,那只是在“模拟”环境,根本无法为实际运行设置门槛。
composer.json 里哪里写 PHP 最低版本?
答案是,必须写在 require 字段里。这里有个常见的误区:很多人会把它放到 config 或者 require-dev 下面,那可就完全走错方向了。
- 正确的写法是
"php": "^8.1",它等价于">=8.1.0 <9.0.0"。建议直接写成">=8.1.0"更清晰,可以避免未来次版本号策略变动带来的意外。 - 如果漏写了这一项,Composer 会默认使用当前执行环境的 PHP 版本进行推断。这直接导致一个后果:不同开发机器上生成的
composer.lock文件可能不一致,为团队协作埋下隐患。 - 特别注意,写成
"php": "8.1.*"或"php": "8.1"是无效的,Composer 不会识别这类模糊的语法。 - 怎么判断写错了?一个很直观的现象:在 PHP 8.0 的环境下执行
composer install居然成功了。这说明require里的 PHP 版本约束根本没生效,大概率就是字段位置放错了,或者语法不合法。
为什么 config.platform.php 不能替代 require.php?
这是个关键问题。config.platform.php 的作用,是让 Composer “假装”自己运行在某个指定的 PHP 版本下,并以此为基础进行依赖解析。但它只是个“模拟器”,并不改变项目实际运行所需的最低版本。
- 举个例子:你本地是 PHP 8.2,但在
composer.json里设置了"config": { "platform": { "php": "8.0.30" } }。那么 Composer 在更新依赖时,只会选择与 PHP 8.0 兼容的包版本。然而,如果你的项目代码里用到了 PHP 8.1 才引入的str_contains()函数,运行时照样会报致命错误。 - 另一个细节:
config.platform.php必须填写完整的版本号,比如"8.0.30"。如果写成"^8.0"或"8.0",这个配置会被 Composer 直接忽略。 - 它的影响范围仅限于
composer update时的依赖求解逻辑,对于composer install时校验当前实际环境这一步,它无能为力。 - 实践中一个常见的误用场景:在 CI/CD 流水线中,只配置了
platform.php来模拟测试环境,却忘了在require中声明最低版本。结果就是构建全部通过,代码一上线就崩溃。
如何验证 PHP 版本约束是否真正生效?
别只满足于 composer install 命令执行成功。要真正放心,得从两个维度来验证:环境拒绝机制是否工作,以及锁文件是否准确反映了目标平台。
立即学习“PHP免费学习笔记(深入)”;
- 环境校验测试:在低于声明版本的 PHP 环境(比如 8.0)下执行
composer install。如果配置正确,你应该会看到明确的错误信息,例如:“Your requirements could not be resolved to an installable set of packages... The requested PHP version is >=8.1.0, but your system has 8.0.30.” - 查看生效配置:运行
composer show --platform命令。这里显示的是config.platform.php设置的值,而不是你系统的实际 PHP 版本。 - 检查锁文件:打开
composer.lock文件,找到"platform": {"php": "..."}这个字段。它的值应该与你设置的config.platform.php完全一致,而不能是空的或者系统的默认值。 - CI 脚本注意:在自动化脚本中,记得为 Composer 命令加上
--no-interaction --prefer-dist --no-progress这些参数,避免交互提示或进度条输出干扰对平台环境的判断。
最后,还有一个极易被忽略的步骤:当你修改了 require 中的 PHP 版本约束后,必须手动执行一次 composer update --lock。这个操作会让 Composer 根据新的约束重新解析依赖关系并更新 composer.lock 文件。如果跳过这一步,旧的 lock 文件依然会按照老的规则锁定依赖,上线后很可能因为某个子依赖需要更高的 PHP 版本而导致整个应用崩溃。这一点,务必警惕。
