必须先执行 composer install 或 update 才能在 composer show --tree 中看到新包,因该命令只读取已安装文件和 composer.lock;--no-dev 是默认行为,需显式添加才能显示开发依赖。

直接运行 composer show --tree 看不到新包?先确认是否已安装
刚在 composer.json 里加了 "monolog/monolog": "^3.0",立马跑 composer show --tree 却没出现?这不是命令错了,是包根本没进 vendor/。Composer 的 --tree 只读 composer.lock 和已安装文件,不解析未执行的声明。
- 必须先执行
composer install或composer update,让包真正落地 - 如果只改了
require-dev,但用了--no-dev(默认行为),它也不会显示——得显式加--dev - 私有仓库或平台包(如
ext-zip)默认不入树,除非加--platform,但一般没必要
查某个包是谁拉进来的?别硬扫树,用 composer why 更准
composer show --tree | grep "guzzlehttp/guzzle" 能找到路径,但容易漏掉间接引用,尤其当缩进深、同名包多时,你可能看到两行 guzzlehttp/guzzle,却分不清哪个是 laravel/framework 拉的、哪个是 spatie/laravel-backup 拉的——版本还可能不同。
-
composer why guzzlehttp/guzzle直接列出所有直接或间接依赖它的顶层包,并附带满足的版本约束(如^7.5) - 想反向查“谁被这个包依赖”?用
composer depends guzzlehttp/guzzle - 这两个命令不画树,但能立刻定位冲突源头,比人工数缩进快 5 倍以上
输出太长看花眼?用 --max-depth 和 grep -A/-B 锁定关键层
运行 composer show --tree laravel/framework,结果刷出 200+ 行,从 symfony/http-kernel 一路钻到 psr/container 再到 php 扩展——你其实只想知道 Laravel 引了哪些一级组件,以及其中有没有你打算替换的 doctrine/dbal。
- 加
--max-depth=1:只看 Laravel 的直接依赖,干净利落 - 加
--max-depth=2:再往下一层,够判断是否引入了冗余 ORM 或 HTTP 客户端 - 配合终端搜索:
composer show --tree | grep -A 3 -B 1 "doctrine/dbal",精准捕获它被谁引用、版本号是多少、上下文是否合理
--no-dev 不是可选项,是默认应开启的过滤习惯
开发依赖(如 phpunit/phpunit、phpstan/phpstan)会把整个分析树撑大一倍以上,且它们和生产环境无关。默认不加 --no-dev,composer show --tree 实际展示的是“构建链”,不是“运行链”。
- 生产部署前审查依赖?必须加
--no-dev,否则你会误以为sebastian/exporter是线上必需包 - CI 流水线中自动检查体积?脚本里写死
composer show --tree --no-dev,避免本地开发环境干扰 - 想临时看全貌?可以,但要意识到:那棵树里至少 30% 的节点,上线后根本不会加载
composer why 来得实在;而最容易被忽略的,恰恰是那个默认不生效的 --no-dev —— 它不报错,但会让你的分析对象悄悄偏移。










