composer show 只显示目标包自身 composer.json 中的 PHP 约束(如 ^8.0 表示最低 8.0.0),不递归检查其间接依赖的 PHP 要求;composer why-not php:X.Y 才能真实探测整个依赖树在该 PHP 版本下的兼容性,列出所有冲突的已安装包及其具体约束。

composer show 查不到间接依赖的最低 PHP 版本?
它只读取目标包自身 composer.json 中的 require.php 字段,比如运行 composer show laravel/framework 看到的 php: ^8.0 || ^8.1 || ^8.2,这个 ^8.0 就是该包声明的最低 PHP 版本(即 8.0.0)。但注意:它不会递归检查 laravel/framework 所依赖的 symfony/console 或 monolog/monolog 各自要求的 PHP 版本——哪怕后者实际要求 PHP 8.1,show 也完全不体现。
composer why-not php:X.Y 是最直接的环境兼容性探针
这不是查“某个包”的最低要求,而是查“当前整个依赖树”能否共存于 PHP X.Y 环境。它把 php:X.Y 当作一个虚拟包来解析冲突:
- 如果本地 PHP 是 7.4,运行
composer why-not php:8.0,输出里出现doctrine/dbal 3.6.3 requires php ^8.0,说明这个间接依赖已卡死升级路径 - 它会列出所有违反约束的已安装包(含 require-dev),不只是顶层依赖
- 不依赖你手动翻每个子包的
composer.json,也不需要提前知道哪个包是瓶颈 - 结果中带具体版本号和约束表达式,可直接定位到冲突源头
composer validate 能发现语法错误,但不校验逻辑合理性
composer validate 只检查 composer.json 里 require.php 的写法是否合法(比如 ^8.0 对、>=8.0.0 也对),但它不会告诉你:
- 你写的
"php": "^7.4"是否和已安装的symfony/http-foundation:^6.0冲突(后者实际要求 PHP 8.0+) -
config.platform.php是否掩盖了真实环境能力,导致show和why-not结果不一致 - 私有包或 path 类型依赖是否在元数据中漏写了 PHP 约束
真正要“自动检测整个项目最低 PHP 版本”,得组合使用
没有单条命令能一步到位。可靠做法是:
- 先用
composer why-not php:7.4、composer why-not php:8.0、composer why-not php:8.1逐档试探,看最早哪一档不报错 - 结合
composer show --tree找出深度依赖中 PHP 要求最高的那个包(比如某dev-master分支要求php: >=8.2) - 注意
composer.json中若存在"config": {"platform": {"php": "8.1"}},所有why-not测试都基于这个“假装的平台”,不是真实环境 - CI 中建议固定 PHP 版本跑
composer install,比靠推测更实在——装不上,就说明真不支持
最低版本从来不是某个包写的数字,而是整个依赖图能共同满足的交集;这个交集必须通过实际解析过程暴露,没法靠静态扫描猜出来。


















