composer show --direct 是唯一能准确列出 composer.json 中 require 字段明文声明的直接依赖的命令;不加 --direct 时,show 默认显示所有已安装包(含传递依赖),outdated 和 show -t 同样默认包含传递依赖,只有显式加 --direct 才聚焦用户亲手声明的依赖。

直接依赖只能靠 composer show --direct 查,其他命令(包括 outdated、show -t)默认都包含传递依赖,不加 --direct 就不是“只看直接依赖”。
为什么 composer show 默认不显示直接依赖
composer show 不加参数时列出所有已安装包,不管它是一级 require 还是某包的子依赖。这在排查“我到底写了哪些 require”时反而干扰大——比如你只写了 guzzlehttp/guzzle,但输出里还混着 psr/http-client、ralouphie/getallheaders 等二十多个间接包。
必须显式加 --direct 才过滤出 composer.json 中 require 字段里明文声明的包:
-
composer show --direct:只列你亲手写进require的包(不含require-dev) -
composer show --direct --no-dev:更干净,排除开发期声明的直接依赖(如phpunit/phpunit) - 注意:它不检查是否实际被代码调用,只认 JSON 结构;删了
require但没跑update,show --direct仍会显示旧包
composer outdated --direct 是查可升级项的正确姿势
很多人用 composer outdated 想找该不该升的包,结果被一堆传递依赖刷屏。不加 --direct 时,它连 symfony/polyfill-mbstring 这种底层补丁包都会报出来——你根本没 require 它,升不升不由你控制。
加 --direct 后,它只对比你 require 里的版本约束和 Packagist 上最新匹配版本:
-
composer outdated --direct:列出所有可安全升级的直接依赖(按语义化版本规则) -
composer outdated --direct --minor-only:只报小版本更新(如2.1.0 → 2.9.9),跳过主版本跃迁 -
composer outdated --direct --no-dev:上线前巡检必备,避免误升 dev 工具链(如把larastan升到不兼容版)
composer show -t . 怎么聚焦直接依赖层
composer show -t . 展开整个项目依赖树,但第一层就是你的直接依赖。问题在于:默认输出太深,容易错过顶层。
两个实操技巧:
- 用
head -n 20截断:composer show -t . | head -n 20,基本能看到全部直接依赖及其一级子依赖 - 配合
grep提取顶层行:composer show -t . | grep "^[a-z]" | head -n 30(Linux/macOS),因为每层缩进用空格,顶层包名开头无空格 - 别信
composer show -t your-package --max-depth=1:它只显示那个包的直接依赖,不是“你项目的直接依赖”
容易忽略的陷阱:dev 依赖也可能是直接依赖
如果你在 composer.json 的 require-dev 里写了 doctrine/dbal,它也是“直接依赖”,只是类型不同。这时:
-
composer show --direct会把它算进去(除非加--no-dev) -
composer show --direct --no-dev才真正只留生产侧的直接依赖 -
composer outdated --direct --no-dev输出为空?不是没包可升,而是你require里真没写任何包——检查composer.json是否漏了require块
真正要锁定“我亲手敲下的 require 行”,--no-dev 不是可选项,是必要条件。否则连 phpunit 都可能混进直接依赖列表里。











