composer why 是查已安装包直接上游依赖的最常用命令,只显示第一层引用者、不展开间接链,支持 --dev 和 --tree 参数,结果基于 composer.lock 且即时可信。

composer why 是最直接、最常用的方式,用来查某个已安装包被谁引入——它不显示间接路径,只告诉你“第一层来源”,但足够快、够准,适合日常排查。
为什么 composer why 比 composer depends 更常用
多数时候你只想知道“谁在 require 这个包”,而不是整条链路。比如升级 monolog/monolog 前,你真正关心的是:是不是 symfony/framework-bundle 在强依赖它?还是某个 dev-only 包偶然带上来的?composer why 一查就明。
- 它默认只查已安装的包,结果即时可信;
composer depends虽然功能更全,但需要 Composer 2.2+,且输出默认不含版本号,容易漏判 - 加
--dev可单独查开发依赖,比如composer why --dev phpunit/phpunit,避免和生产依赖混在一起 - 不加参数时,它会自动忽略未安装的包(比如只写在
require-dev里但当前没装),不会报错,而是静默跳过——这点比手动翻composer.lock更省心
composer why -t 展开完整依赖链的注意事项
加 -t(即 --tree)确实能从根项目开始逐级展开,但要注意它的缩进逻辑不是“理论依赖”,而是“当前 composer.lock 实际解析出的路径”。
- 如果你刚改了
composer.json但还没composer update,-t输出的就是旧链路,可能和你预期不符 - 遇到某一层突然中断(比如停在
psr/log就没了),大概率是该包通过provide声明虚拟包,Composer 不再向下解析——这不是 bug,是设计使然 - 输出中带
[dev]标记的,说明来自require-dev;没标记的才是生产环境真实依赖
查不到结果时先确认这三件事
运行 composer why vendor/package-name 返回 “Could not find package” 或 “No dependencies”,别急着怀疑命令,先检查:
- 包名是否全小写、带斜杠,比如必须是
monolog/monolog,不能写成Monolog/Monolog或漏掉/ - 该包是否真在
vendor/目录下存在——有些包只在require-dev里,而你执行时没加--dev,或当前环境没装 dev 包 - 是否在项目根目录执行?这个命令不支持跨目录调用,
cd错位置就会查空
真正容易被忽略的是:所有这些命令反映的都是 composer.lock 的快照,不是 composer.json 的声明。如果你刚删了某行 require 却没 update,why 依然会显示它被引用——因为锁文件还没更新。











