composer show --tree 是查看已安装依赖树的唯一可靠命令,它基于 vendor/ 和 composer.lock 输出真实快照,非 composer.json 的理想状态;查未安装包用 --remote,反向依赖用 composer show --who,溯源需 --tree,且依赖树不等同代码调用关系。

composer show --tree 是查看依赖树的唯一可靠命令
别再搜 composer tree——它根本不是 Composer 内置命令,是早年插件遗留的混淆概念。真正能用、稳定、无需额外安装的,只有 composer show --tree。
这个命令读的是当前 vendor/ 目录下**已实际安装**的包结构,反映的是 composer.lock 解析后的真实依赖快照,不是 composer.json 里写的“理想状态”。
- 必须在项目根目录运行,且目标包得已安装;否则报错:
Package not found - 想查未安装包的依赖?加
--remote:例如composer show --remote --tree monolog/monolog - 不支持
--depth参数限制层级,真要截断只能靠head -n 50或重定向到文件后人工看
查“谁用了这个包”用 composer show --who,不是 depends
composer depends 是个陷阱:2.4+ 才有,且默认关闭,需先执行 composer config experimental.show-depends true 才能用——但没必要。
官方早已把反向依赖能力收进 composer show --who(≥2.2),它直接列出所有**直接声明依赖**该包的已安装包,结果干净、无歧义。
- 示例:
composer show --who psr/log输出所有 require 了psr/log的包(如monolog/monolog、laravel/framework) - 它不递归展开下游链路(比如 A → B → C,只显示 B 依赖 C),这是设计使然,不是 bug
- 不区分
require和require-dev,若只想看生产环境依赖谁用了它,得配合--no-dev过滤
定位“为什么装了这个包”必须加 --tree
composer why vendor/package 默认只返回一级来源,比如查 monolog/monolog 可能只显示 laravel/framework,但你真正想知道的是:“我自己的 composer.json 里哪行写了它?”
这时候不加 --tree 就等于白查——它不会自动向上追溯到项目顶层。
- 正确姿势:
composer why --tree monolog/monolog,输出会像:monolog/monolog<br>└── laravel/framework<br> └── your-project-name dev-main
- 末尾的
your-project-name dev-main表示源头是你自己项目的composer.json中的require - 若某行结尾带
[dev],说明来自require-dev;若中断在某个包名后没继续,可能是那个包用了provide声明虚拟包
依赖树 ≠ 代码调用图,别拿它当静态分析用
composer show --tree 展示的是“Composer 安装时决定拉哪些包”,和“PHP 代码里实际 new/use 了谁”是两回事。
比如一个包声明依赖 symfony/console,但你的代码一行都没用过它——--tree 依然会把它画进去;反过来,如果某处 require_once 手动加载了未声明的类,--tree 根本看不见。
- 真要分析跨包调用或排查“幽灵依赖”,得用
deptrac或phpstan/dependency-analyser这类基于 AST 的工具 -
deptrac默认不读composer.lock,它扫描的是use和new,所以首次运行慢、报告里一堆uncovered不代表有问题,只是规则没覆盖到 - 大型项目里,把
--tree当成“安全审查依据”容易误判——它只管声明与安装,不管运行时是否真用
replace、provide、平台约束……这些都会让同一份 composer.json 在不同环境下生成完全不同的树。别信一次输出,要查就带着上下文一起看。










