composer show --tree 是生产环境依赖树分析的唯一开箱即用方案,直接读取 composer.lock 中已解析的实际依赖关系,不依赖插件、不触发网络请求,显示运行时实际加载的包及其子依赖。

composer show --tree 是生产环境依赖树分析的唯一开箱即用方案
它不依赖插件、不需额外安装、不触发网络请求,直接读取 composer.lock 中已解析的实际依赖关系——这正是生产环境需要的「真实快照」。注意:它显示的是运行时实际加载的包及其子依赖,不是 composer.json 里声明的模糊约束。
常见错误现象:composer tree 报错 Command "tree" is not defined,或装了旧版插件后导致 composer update 失败;这类命令根本不在 Composer 2+ 官方支持范围内。
-
composer show --tree不加参数会输出全量依赖树,对中大型项目极易刷屏,建议配合grep或less:如composer show --tree | grep -A3 "guzzlehttp" - 必须指定已安装的包名(区分大小写),
composer show --tree foo/bar对未安装包会报Package not found - 不支持
--depth或缩进控制,想限制层级只能靠外部截断,例如composer show --tree monolog/monolog | head -n 20
为什么不能用 composer why 或 composer depends 查生产依赖
这两个命令默认只查「直接声明的依赖来源」,而生产环境中大量包是通过间接依赖(transitive dependency)引入的,比如 A → B → C,你在 composer.json 里只写了 A,C 就不会被 composer why c/c 显示出来。
正确做法是加 -t(即 --tree)参数才会展开完整路径:
-
composer why -t monolog/monolog:查谁拉入了 monolog,以及它的每一层上游 -
composer depends -t guzzlehttp/guzzle:查哪些包依赖了 guzzle,含嵌套路径 - 若返回空,大概率是上游用了宽泛约束(如
"^2.0"或"*"),导致 Composer 在 lock 文件里选了某个“不显眼”的中间包作为载体
可视化依赖图仅在调试阶段有用,别上生产
像 baethon/composer-graph 这类工具依赖 dot 命令(Graphviz),生成 SVG/PNG 图。但它读的是 composer.lock 的静态结构,无法反映运行时 autoload 加载顺序、platform 配置覆盖、或 classmap 优化后的实际行为。
更关键的是:它会把 require-dev 包也画进去,而生产环境通常用 --no-dev 安装,图和实际不符。
- macOS 装 Graphviz:
brew install graphviz(别只装 php extension) - Ubuntu/Debian:
sudo apt install graphviz - Windows:官网下载安装包,务必勾选「Add Graphviz to the system PATH」
- 生成命令:
composer graph --format=svg > deps.svg,但该图仅适合本地快速定位循环引用或意外引入路径
真正影响生产的不是依赖树,而是 autoload 加载顺序
依赖树告诉你「有哪些包」,但 vendor/autoload.php 决定「谁的类先被加载」。两个包若声明了同名类(如 Helper),谁在 autoload chain 里注册得早,谁就生效——这种覆盖静默发生,不报错但行为突变。
- 执行
composer dump-autoload -o会生成 classmap,它优先于 PSR-4,且顺序固定,可缓解不确定性 - 检查冲突:运行
composer show -t,看同一命名空间是否被多个包同时声明 - 临时验证:在入口文件加
var_dump(spl_autoload_functions());,观察实际 loader 注册顺序
依赖树再清晰,也掩盖不了 autoload 注册顺序这个底层事实。排查线上类找不到、方法不存在、行为不一致,第一步永远不是画图,而是确认 classmap 是否启用、PSR-4 路径是否重叠、以及 vendor 目录下真实存在的类文件是否被预期的 loader 拿到。











