composer why-not 和 composer show --tree 是定位 composer 依赖冲突最高效的方式,前者精准揭示阻塞源头(需指定完整包名和精确版本号,输出从下往上读),后者展示 composer.lock 中已锁定的真实依赖树,暴露间接路径、replaced/provided 等隐藏问题。

直接运行 composer why-not 和 composer show --tree,别删 vendor 或 composer.lock —— 这是最快定位冲突源头的方式,90% 的“装不上”问题靠这两个命令就能闭环。
报错里出现 “don’t install X” 怎么读
这不是说 X 包坏了,而是某条依赖链联合封杀了你要的版本。关键信息藏在报错开头或加 -v 后的 Conclusion 段里:
- 例如
Root requires monolog/monolog ^2.0, but package-x v3.1.0 requires monolog/monolog ^1.25→ 真正卡住的是package-x,不是monolog - 如果报错末尾写
found 3 packages that conflict,说明有多个包对同一依赖提出互斥要求,得逐个查 -
require-dev里的包(如phpunit/phpunit)也参与解析,哪怕你只跑composer install
composer why-not vendor/package:version 必须带具体版本号
不写版本号,命令就无效;写错格式(比如加引号、用 ^)也会返回空或误导结果:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 正确:
composer why-not guzzlehttp/guzzle:7.4.5(精确版本) - 正确:
composer why-not monolog/monolog:2.9.0 - 错误:
composer why-not "guzzlehttp/guzzle:^7"(引号 +^会让 Composer 自行推导,不是你想要的路径) - 错误:
composer why-not guzzlehttp/guzzle(缺版本号,无输出) - 输出是从下往上读:最后一行是你
composer.json的根声明,往上每行的(required by)就是阻塞点
查真实依赖结构,别信 composer.json 里写的“愿望清单”
composer show --tree 显示的是 composer.lock 里已锁定的真实快照,它暴露你根本没意识到的间接路径:
- 查某个包被谁拉进来:
composer show --tree | grep "symfony/console" - 过滤关键段:
composer show --tree monolog/monolog | grep -A5 -B5 "guzzlehttp/guzzle" - 看到某包标着
(replaced)或(provided),得去它自己的composer.json里确认是否真能替代 - 如果
composer show --tree里没出现你怀疑的包,但它又在报错里被提到,大概率是require-dev或已废弃配置残留
复杂点在于:冲突不是“找不到包”,而是“找不到所有包都同意的版本交集”。一个 conflict 字段、一个 replace 声明、甚至 minimum-stability 设置,都可能让 SAT 求解器直接放弃——这些细节不会出现在报错第一屏,但会决定你花 5 分钟还是 5 小时解决它。










