composer why-not 是第一个必须跑的诊断命令,它不修改任何文件,仅通过反向回溯 composer.json 和 composer.lock 中的 require、conflict 及 platform 约束,精准定位首个不可绕过的硬性冲突源,输出每一行均指向真实阻断点。

composer why-not 是第一个必须跑的命令
它不修改任何东西,只告诉你“为什么这个版本装不上”,输出里每一行都指向一个真实存在的硬性约束。比如你想装 laravel/framework:v10.0 却失败,运行 composer why-not laravel/framework:10.0.0,结果里出现:
myapp/core dev-main requires laravel/framework ^9.0spatie/laravel-backup v8.0.0 requires laravel/framework ^9.0phpunit/phpunit 10.5.0 requires illuminate/support ^9.0
这三行不是并列关系,而是从下往上读:最底下那行才是你项目根 composer.json 的原始要求,往上是传递链中真正卡住升级的包。注意必须带精确版本号(如 10.0.0),写 ^10.0 或 10.* 都会报 Package not found。
用 composer show --tree 看清真实依赖路径
默认 composer show --tree 只显示一级依赖,容易漏掉深层冲突。真正有用的是指定包名并配合 grep:
-
composer show --tree monolog/monolog | grep -A5 -B5 "guzzlehttp/guzzle"—— 查看 monolog 和 guzzle 是否在同一条路径上、版本是否一致 -
composer show --tree | grep "symfony/console"—— 找出所有引入symfony/console的包,尤其注意末尾带(locked to 5.4.32)的行,说明该版本已被composer.lock固定 - 终端宽度不够会导致缩进错乱,建议加
| less -S避免换行干扰层级判断
如果同一个包(如 symfony/console)在不同缩进层级反复出现,且版本不一致(^5.4 vs ^6.0),冲突基本就在这里。
composer prohibits 直接锁定“死守旧版”的包
当你想升级某个包却卡住时,composer prohibits 比 why-not 更聚焦。例如升级失败提示无法安装 guzzlehttp/guzzle:^7.8,直接运行:
composer prohibits guzzlehttp/guzzle:^7.8
输出会明确列出谁在拉低版本:
myorg/sdk v2.3.0 requires guzzlehttp/guzzle ^6.5firebase/php-jwt v6.10.0 requires guzzlehttp/guzzle ^7.2
这里 myorg/sdk v2.3.0 就是明确的源头——不是模糊地说“某个依赖”,而是具体到哪个包、哪个版本、提了什么约束。如果输出为空,说明没有包显式 require 它,可能来自 replace 或 conflict 字段,得查 composer.lock 或对应包的 composer.json。
别跳过 --dry-run -v 的末尾日志
composer update --dry-run -v 不改文件,但会完整走一遍解析流程。关键不是看前面几百行,而是直接翻到最后 10 行:
找到类似这样的句子:
Found conflicting requirements for symfony/console: ^5.4 and ^6.0Because package-a v2.1 requires symfony/console ^5.4, and package-b v3.0 requires symfony/console ^6.0
反复出现的包名(如 symfony/console、monolog/monolog)就是枢纽,它们被多个上游包分别绑定了互斥版本。如果看到 your-project-name 出现在冲突链里,说明是你自己 composer.json 里的某行约束太窄,比如同时 require 了两个不兼容的 SDK。
require-dev 中的包默认参与解析,哪怕你部署时加了 --no-dev,它们依然会影响 update 和 install 的决策。最容易被忽略的是 phpunit/phpunit 这类工具链包,它可能通过 orchestra/testbench 间接锁死了 laravel/framework 版本。


















