composer show -t是当前唯一稳定、无需插件的依赖树命令,读取vendor/和composer.lock真实快照,需指定包名(如.或guzzlehttp/guzzle),加--no-dev可过滤开发依赖,缩进仅表示require声明层级而非加载顺序。

composer show -t 是当前唯一稳定、无需插件、能直接看到真实依赖快照的命令,但纯文本树形结构在深度嵌套时极易误读——这不是你眼花,是工具设计如此。
为什么 composer show -t 输出缩进容易看错
缩进只表示声明层级,不是加载顺序,也不是重要性排序。每级缩进对应一个 require 声明:比如 guzzlehttp/guzzle 下缩进出现 psr/http-client,说明 Guzzle 的 composer.json 明确写了它;同一包出现在不同缩进(如 2 级和 4 级),大概率被多个上游包分别引入,版本不一致时就会冲突。
常见误读包括:
- 把缩进当“调用链”或“自动加载顺序”,其实 autoload 行为由
classmap/psr-4注册顺序决定,和树无关 - 看到某包重复出现就断定冲突,但可能只是不同路径最终解析到同一版本,得配合
composer show vendor/package确认实际安装版 - 终端宽度不够导致换行错位,缩进视觉错乱,建议加
| less -S或重定向到文件后查看
怎么精准聚焦某条依赖路径
全量输出动辄上千行,必须用参数过滤,否则等于没查:
- 查整个项目:用
composer show -t .(点号代表当前项目),不能省略包名 - 只看生产环境链路:
composer show --no-dev -t .,--no-dev必须放在-t前面,否则无效 - 查某个包的下游依赖:
composer show -t guzzlehttp/guzzle,它从 Guzzle 开始向下展开,不扫全量 - 查未安装包的潜在依赖:
composer show --remote -t monolog/monolog,适合安装前评估
注意:composer show -t 读的是 vendor/ 和 composer.lock 的实际快照,不是 composer.json 的理想状态。
反向查“谁用了这个包”别用 depends
composer depends 是实验功能(2.4+ 默认关闭),遇到 provide、replace 或 path 类型仓库时容易漏判。真正可靠的是:
-
composer show --who psr/log:列出所有直接require了它的已安装包 - 加
--no-dev过滤开发依赖:composer show --who --no-dev psr/log - 结果为空 ≠ 没人用 —— 可能是通过虚拟包(如
psr/log-implementation)间接提供,此时应回头看composer show -t .全局结构
想确认是不是你自己 composer.json 里写的,必须用 composer why --tree monolog/monolog,末尾出现 your-project-name dev-main 才算溯源成功。
什么时候必须上 Graphviz 可视化
当 composer show -t 输出超过 200 行、同一包在 5+ 层深度反复出现、或需要判断多版本共存是否真冲突时,纯文本已失效。
可行方案是 composer-unused + dot:
- 先装 Graphviz:
brew install graphviz(macOS)、apt install graphviz(Ubuntu) - 全局装插件:
composer global require composer-unused/composer-unused - 生成 dot 文件:
composer-unused --format=dot > deps.dot - 渲染成图:
dot -Tpng deps.dot -o deps.png
注意箭头方向默认是“被依赖”(A → B 表示 B 用了 A),若想改成“依赖方向”,加 --reverse 参数。私有包或 path 类型仓库需手动加 --scan-path,否则图中会缺节点。
真正难处理的从来不是命令怎么写,而是看到图里几十个箭头交叉指向同一个包时,得判断哪条路径锁死了版本、哪个 provide 声明绕过了约束——这些信息,树和图都不会直接告诉你。











