最准的依赖层级查看命令是composer show --tree,但需指定完整包名(如guzzlehttp/guzzle)、加--no-dev过滤开发依赖,并用less -S避免缩进错位;composer why --tree用于查引入来源,但须确保包已安装且必要时加--dev;composer depends仅查composer.json显式声明,不递归扫描vendor内嵌套依赖。

直接看依赖层级,用 composer show --tree 最准;查谁拉进来的,优先用 composer why --tree;别信 composer depends 默认行为,它不查间接依赖,也容易因版本过低报错。
为什么 composer show --tree 输出乱、找不到重点?
它默认展开整个项目依赖树,几百行缩进混在一起,根本分不清哪层是你的直接依赖、哪层是某 SDK 偷偷带进来的。关键不是命令错了,而是没加过滤和限定。
- 加包名聚焦:必须写全
composer show --tree vendor/package(比如composer show --tree guzzlehttp/guzzle),不加包名等于自找麻烦 - 终端宽度影响缩进:太窄时缩进被截断,导致层级错位,临时用
composer show --tree --no-dev | less -S横向滚动查看 - 输出里带
[dev]的,说明来自require-dev,上线部署时可能被跳过,别当成生产依赖 - 同一包在多条路径下重复出现(比如
symfony/polyfill-php80出现在 4 个地方),不代表装了 4 份,只是 Composer 树形展示的副作用
composer why --tree 查不到包?先确认三件事
它返回空或 “No dependencies”,不等于这个包没被用——大概率是你没站在正确的上下文里查。
- 包必须已安装到
vendor/,否则why完全看不见;运行ls vendor/vendorname/packagename确认存在 - 默认不查
require-dev下的依赖链,如果目标包只在测试工具里被引用(比如phpunit/phpunit→sebastian/exporter),得加--dev:composer why --tree --dev sebastian/exporter - 如果包是通过
provide声明虚拟包(如psr/log被多个包提供),why可能静默失败,这时得换composer show --tree | grep -B3 -A3 "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+ 人工向上翻 - 即使版本够,
composer depends vendor/package仍不会告诉你 “laravel/framework的子依赖带进了它”,它只回答“谁在你自己的composer.json里写了它”
真正复杂的地方:依赖树不是静态快照
composer show --tree 显示的是当前 composer.lock 解析后的结果,受本地 PHP 版本、config.platform.php、甚至 platform 配置干扰。比如你本地是 PHP 8.2,但锁文件里配置了 "platform": {"php": "8.1"},那树里显示的可选版本就和实际运行环境不一致。更隐蔽的是 autoload 加载顺序——两个包都注册了同名类,谁先注册谁生效,这种冲突 show --tree 根本不体现,得靠 composer dump-autoload -o 后检查 vendor/composer/autoload_classmap.php 才能定位。


















