composer why 查“谁显式要求它”,只显示直接在 require 或 require-dev 中声明目标包的上游包,不包括传递依赖;输出含精确版本约束,为空则说明无显式引用。

composer why 不是查“谁用了它”,而是查“谁显式要求它”
composer why 输出的是直接在 require 或 require-dev 字段里写了该包的上游包,不包括传递依赖。比如你运行 composer why monolog/monolog,它只列出你的 composer.json 里直接声明了它的包,或者某个已安装扩展包的 composer.json 中明确写了 "monolog/monolog": "^2.0" —— 它不会告诉你 laravel/framework 间接依赖了它。
这个命令真正有用的地方在于快速确认:是不是你自己或某个扩展包“主动拉入”了冲突源。常见误判是看到输出里有 topthink/think-swoole 就以为它是元凶,其实它可能只是被动继承了 TP5 的旧约束,而真正卡住升级的是它依赖的另一个包。
- 如果输出为空,说明没有包在
require级别声明它——那它大概率是被某个包的require-dev或conflict字段拖住的 - 如果输出里出现多个包,但版本约束不一致(如一个写
^1.25,另一个写^2.8),这就是冲突的显性信号 - 注意看每行末尾的版本号,它来自那个包自己的
composer.json,不是你项目当前装的版本
composer why-not 才是定位“第一个拦路虎”的关键
当报错是 Conclusion: don't install thinkphp/framework v6.0.10,你应该立刻运行:composer why-not thinkphp/framework:6.0.10。它会模拟 Composer 安装这个版本的过程,并告诉你在哪一层被阻断。
输出通常包含三类信息:你项目根 composer.json 的原始需求、某个已安装包的硬性约束(如 spatie/laravel-backup 的 "conflict": {"thinkphp/framework": ">=6.0"})、以及 PHP 或扩展限制(如 ext-intl 未启用)。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 必须指定完整包名+版本号,
composer why-not thinkphp/framework会报错 - 如果提示
[InvalidArgumentException] Package not found,说明这个包还没出现在你的composer.lock或composer.json里,它压根没参与当前解析 - 输出中带
requires php的行要重点检查,很多 TP6 冲突实际是 PHP 8.0+ 和某扩展包的php ^7.4矛盾
composer prohibits 告诉你“谁在死守旧版本”
当你想升级 guzzlehttp/guzzle 到 ^7.8 却失败时,composer prohibits guzzlehttp/guzzle:^7.8 会列出所有强制要求旧版的包,比如:myorg/sdk v2.3.0 requires guzzlehttp/guzzle ^6.5。
这比翻 composer.lock 快得多,而且能直接看到约束来源是哪个具体版本的包——不是模糊的“某个依赖”,而是 myorg/sdk v2.3.0 这个确定实体。
- 它只查“已安装且锁定了版本”的包,所以结果非常精准
- 输出里如果出现
replaces或provides,不用管;真正起作用的是标着requires的那几行 - 如果某行写着
myapp/core dev-main requires guzzlehttp/guzzle ^6.0,那就得去改myapp/core的composer.json,而不是你自己的项目
依赖树太深?用 composer show --tree + grep 定位隐藏链
有些冲突藏在第三层甚至第四层依赖里,composer why 和 why-not 都看不到。这时用 composer show --tree guzzlehttp/guzzle 展开整棵树,再配合 grep 过滤关键路径。
例如:你发现 symfony/console 总是被锁在 5.4.32,但你想升到 6.4,就运行:composer show --tree guzzlehttp/guzzle | grep -A3 -B3 "symfony/console",很快就能看到是 phpunit/phpunit 的某个子依赖在拉低版本。
- 输出中带
(locked to X.Y.Z)的节点,说明这个版本已在composer.lock固定,删 lock 文件或加--with-all-dependencies才可能松动 - 树越深,越要关注第二层包(即直接依赖你的包)的
composer.json,它们的require字段往往才是真正的源头 - 别忽略
require-dev里的包,phpunit/phpunit对symfony/yaml的版本要求,经常和主框架冲突

















