唯一稳定查依赖树的命令是 composer show --tree,它基于 vendor/ 和 composer.lock 真实快照,需在项目根目录运行;查谁依赖某包用 composer show --who,溯源自身声明用 composer why --tree,未安装包则加 --remote。

直接用 composer show --tree,别搜 composer tree
它不是 Composer 内置命令,是早年第三方插件遗留的混淆概念。现在唯一稳定、无需安装、不依赖实验配置的方案,就是 composer show --tree。这个命令读的是 vendor/ 和 composer.lock 的真实快照,反映的是“已经装进去”的依赖结构,不是 composer.json 里写的理想状态。
- 必须在含
composer.json的项目根目录运行,否则报错或输出为空 - Composer 版本低于 2.0 会提示
Command "show" is not defined,先执行composer self-update - 不加包名就扫全量——几百行起步,基本没法读;想查某个包,直接跟上名字:
composer show --tree guzzlehttp/guzzle -
--tree是show子命令的参数,不是独立命令;写成composer tree或composer show tree都会失败
查“谁用了这个包”:用 composer show --who,不是 composer depends
composer depends 是 2.4+ 实验功能,默认关闭,还得先跑 composer config experimental.show-depends true,而且遇到 provide、replace 或本地 path 仓库时容易漏判。而 composer show --who psr/log 直接列出所有在 require 或 require-dev 中声明了它的已安装包,干净、确定、无歧义。
- 输出只显示“直接声明依赖”,比如 A → B → C,
--who只显示 B,不展开 A;这是设计,不是 bug - 要过滤开发依赖,加
--no-dev:composer show --who --no-dev psr/log - 如果结果为空,不代表没人用——可能是通过
provide虚拟包间接提供,此时应回头看composer show --tree全局结构
为什么装了这个包?必须加 --tree 才能溯源到你自己
composer why monolog/monolog 默认只返回一级来源(比如 laravel/framework),但你真正想知道的是:“我自己的 composer.json 哪一行写了它?” 这时候不加 --tree 就等于白查。
- 正确姿势:
composer why --tree monolog/monolog,输出末尾出现your-project-name dev-main,才说明源头是你自己项目的require - 若结尾带
[dev],说明来自require-dev - 如果树在某一层中断(比如停在
laravel/framework就没了),可能是它用了provide声明虚拟包,没继续向下解析
未安装的包也能查依赖,但得加 --remote
想评估一个还没装的包会不会拉进一堆旧版本组件?不用先 require 再删,直接用 --remote:
-
composer show --remote --tree doctrine/orm—— 查远程包的依赖树,不碰本地环境 - 它不支持
--depth或--max-depth,真要截断只能靠终端工具:composer show --remote --tree monolog/monolog | head -n 50 -
--remote查的是 Packagist 上该包最新稳定版的composer.json,不是你锁死的旧版;如需看特定版本,得加@v2.13.0后缀
依赖树不是代码调用图,它不反映 use、new 或函数调用关系,只反映 Composer 解析出的包级依赖。最常被忽略的点是:不加 --no-dev 时,测试工具链(比如 phpunit 拉的 sebastian/diff)会混进生产依赖树里,误导你判断冲突来源。










