composer why 用于查“谁显式要求该包”,只显示直接在 require 或 require-dev 中声明目标包的上游包及其精确版本约束;若输出为空,说明该包是项目根 composer.json 中直接声明的,而非被其他包间接引入。

composer why 不是用来查“谁用了它”,而是查“谁把它拉进来的”——如果输出为空,说明它没被任何已安装包间接依赖,大概率是你自己写在 composer.json 的 require 或 require-dev 里。
为什么 composer why monolog/monolog 没输出?
这不是命令失效,而是它按设计只展示「间接依赖路径」。直接写在你项目 composer.json 中的包,composer why 默认跳过不查。
- 先运行
composer show monolog/monolog确认它真在当前锁文件里;如果返回空,说明根本没装上 - 再打开
composer.json,搜索"monolog/monolog"—— 若存在,就是你主动 require 的 - 若想查它被哪些包“用到”,得换命令:
composer depends monolog/monolog(Composer 2.2+) - 注意大小写和斜杠:
monolog/monolog≠monolog/monolog-dev,输错就查不到
composer why --tree 能看到完整路径,但容易断在 provide
加 --tree 是唯一能看清层级的方式,但它会在遇到 provide 声明时戛然而止——比如某包声明 "provide": {"psr/log-implementation": "*"},composer why --tree psr/log-implementation 就会停在那一层,不往下展开真实实现。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 典型输出:
my-project └── laravel/framework ^10.0 └── monolog/monolog ^2.0 - 若中间某行后没了下级,大概率是上游包用了
replace或provide替代了目标包 - 此时要定位真实来源,得手动查
vendor/composer/installed.json,搜"monolog/monolog",看"replaced"或"provides"字段
composer depends 和 composer why 别混用
两个命令语义相反:why 回答“谁让我进来”,depends 回答“我让谁离不开”。它们默认行为也不同,容易误判。
-
composer why vendor/package:只查require,不查require-dev,除非加--dev -
composer depends vendor/package:默认只查require,加--all才包含require-dev中的依赖者 - 老版本 Composer(depends,只能靠
composer show -t | grep -A 3 -B 3 "package-name"配合筛选 - 若
depends报Package not found,先确认是否输全了 vendor 名,如doctrine/orm不是doctrine
真正卡住升级的,往往不是 why 显示的那条路径
composer why 只返回最短路径(字典序最小),但冲突常藏在另一条未显示的依赖链里。比如它显示 foo/bar 拉入了旧版 guzzlehttp/guzzle,可实际拦住升级的是 bar/baz 的 conflict 字段。
- 查完
why,立刻补一句:composer prohibits guzzlehttp/guzzle:^7.8,它会列出所有“死守旧版”的包及其具体版本 - 若输出含
root requires,重点盯你自己的composer.json,那里可能写了"guzzlehttp/guzzle": "6.*"这类硬约束 - 别忽略
platform配置:CI 中设了"config": {"platform": {"php": "7.4.33"}},会导致why-not和prohibits都误报 PHP 版本冲突










