composer show --tree --all 不可靠,因为它基于 vendor/composer/installed.json 快照而非实时解析 composer.json 和 lock 文件,混杂 dev-only、残留包、replace/conflict 失效项及未裁剪的平台配置分支。

composer show --tree --all 确实能显示所有已安装包的完整依赖树,但它在实际使用中容易产生误导——它不区分“直接依赖”和“间接依赖”,也不过滤 dev-only 包,更不会反映当前 composer.json 的真实约束关系。
为什么 composer show --tree --all 显示的树看起来很全,却不可靠
这个命令会递归展开每一个已安装包(包括 require-dev 中的包),甚至包含被 replace 或 conflict 排除但因历史安装残留仍存在于 vendor/ 的包。它读取的是 vendor/composer/installed.json 的快照,而非实时解析 composer.json + lock 文件的依赖图。
- 若某包被
conflict声明但尚未卸载,它仍会出现在树中 -
--all会强制显示所有版本分支(如dev-main、1.x-dev),干扰对稳定依赖的判断 - 无法体现平台配置(如
platform.php)导致的版本裁剪
想看真正生效的依赖路径?用 composer depends 和 composer show --tree 组合
要定位某个包为何被装上,或验证某依赖是否真的被项目直接引用,优先用 composer depends;要看精简、可读的运行时依赖树,去掉 --all,只用 composer show --tree:
-
composer depends monolog/monolog查谁拉入了 monolog(含 transitive 路径) -
composer show --tree vendor/package只展开指定包的子树,避免全量爆炸 - 搭配
COMPOSER_MEMORY_LIMIT=-1防止大项目报Allowed memory size exhausted
替代方案:用 composer why-not 和 composer prohibits 定位冲突根源
当依赖树里出现意外版本或缺失包,--tree --all 只是现象,不是原因。真正有用的是诊断命令:
-
composer why-not phpunit/phpunit:10.0显示阻止升级的具体约束(来自哪个 require / platform / conflict) -
composer prohibits guzzlehttp/guzzle ^7.0列出所有与该版本冲突的已安装包及其原因 - 这些命令直读
composer.lock和约束表达式,结果比--tree --all的静态快照更可信
依赖树不是越全越好,而是越贴近 lock 文件解析逻辑越准。别让 --all 给你一种“全都看见了”的错觉——它展示的是 vendor 目录的现状,不是 Composer 解析器的实际决策路径。










