最准、最常用且兼容 Composer ≥ 2.2 的命令是 composer show --tree,需加包名或过滤参数才聚焦;默认输出是完整依赖树,含底层包,目标包可能深埋缩进中;--no-dev 排除开发依赖,| less -S 解决宽度问题;composer why --tree 查主动引用者,非间接使用,需确认包已安装、是否在 require-dev 中、是否为虚拟包;composer depends 仅扫描项目 composer.json 显式声明,不查 vendor 嵌套依赖,低版本无此命令;vendor/composer/installed.json 是滞后快照,验证安装应以 ls vendor/... 或 composer show 为准。

最准、最常用、且兼容 Composer ≥ 2.2 的命令是 composer show --tree,但必须加包名或过滤参数,否则输出不可读、不聚焦。
为什么 composer show --tree 默认输出全是“乱码”缩进?
它不是乱码,是完整依赖树的原始展开:从 root 包开始递归列出所有已安装包,包含 symfony/polyfill-php80、composer/xdebug-handler 这类底层支撑包,而你关心的 guzzlehttp/guzzle 可能埋在第 20 行缩进里。
- 加包名精准聚焦:
composer show --tree guzzlehttp/guzzle—— 只显示该包及其下游依赖 - 加
--no-dev排除干扰:composer show --tree --no-dev monolog/monolog—— 生产环境分析必备 - 终端宽度太窄时缩进错位?用
composer show --tree --no-dev | less -S横向滚动查看 - 输出里带
[dev]标记的,说明来自require-dev,上线部署时不会被装
composer why --tree 查不到包?先确认这三件事
它查的是「谁主动 require 了这个包」,不是「谁间接用到了它」。查不到 ≠ 没人用,大概率是上下文不对。
- 包必须已安装到
vendor/目录下,运行ls vendor/guzzlehttp/guzzle确认存在 - 默认不查
require-dev下的链路;如果目标包只被phpunit/phpunit引用,得加--dev:composer why --tree --dev sebastian/exporter - 若包是通过
provide声明的虚拟包(如psr/log),why会静默失败,此时改用composer show --tree | grep -B2 -A2 "psr/log"手动定位
composer depends 为什么总报错或为空?
它根本不是 why 的替代品,设计目的不同:只扫描你项目 composer.json 中显式声明的 require 和 require-dev,完全不读 vendor/ 里的嵌套 composer.json。
- 报
Could not find package?90% 是包名拼错:monolog/monolog不等于Monolog/monolog,斜杠不能省,大小写敏感 - 报
Command "depends" is not defined?Composer 版本低于 2.5,运行composer --version确认;旧版只能退回到composer show --tree+ 人工向上翻 - 包确实存在于
vendor/但depends查不到?说明它是被某个已安装包「偷偷带进来的」,比如某 SDK 的子依赖——这时必须用composer show --tree | grep your/package定位层级,再对上层包重复执行show --tree
别信 vendor/composer/installed.json 是“权威源”
它只是 composer install 或 update 后生成的一次性快照,内容滞后于真实状态。
- 你删了
composer.json里的monolog/monolog但没跑composer update?installed.json里还留着它 - 你改了
composer.json但没 install?installed.json仍是旧结构,composer show --tree也会显示过期结果 - 想验证某个包是否真装上了?最可靠方式是
ls vendor/vendorname/packagename或composer show vendorname/packagename看是否返回版本号


















