composer show 是最轻量可靠的实时依赖清单来源,直接读取 vendor/ 下实际安装结果而非 composer.json 声明,加 -a 列出全部包,--format=json 输出结构化数据供解析。

composer show 能直接列出所有已安装依赖
项目里运行 composer show 就能看到当前 vendor/ 下所有包的名称、版本和简短描述,这是最轻量、最可靠的实时清单来源。它不读取 composer.json 的声明,而是读取实际安装结果,所以能反映 lock 文件生效后的最终状态。
常见错误是只看 composer.json —— 那只是“想装什么”,不是“装了什么”。比如手动删过某个 vendor/ 子目录,或 composer install 时跳过了某些平台约束,composer.json 就会和真实环境脱节。
- 加
-s参数可显示包的源(如dist或source) - 加
--tree可看依赖层级,但输出易刷屏,建议配合grep过滤,例如:composer show --tree | grep monolog - 不加任何参数时默认只显示顶层包;加
-a才列出全部(含被间接引入的)
用 composer show --format=json 导出结构化清单
需要把依赖写入 CI 日志、做版本比对或交给其他工具处理时,--format=json 是唯一靠谱的选择。它输出的是标准 JSON,字段稳定,不含颜色、缩进或 ANSI 控制符,解析安全。
注意:这个 JSON 不是 composer.lock 的简化版,而是 composer show 命令执行结果的序列化,因此不含哈希、zip 下载地址等 lock 特有字段,但包含每个包的 homepage、description 和 type 等元信息。
- 导出到文件:
composer show --format=json > deps.json - 如果只需要包名+版本,用
jq提取:composer show --format=json | jq '.[] | {name: .name, version: .version}' - 别用
composer install --dry-run --verbose模拟——它不保证输出格式稳定,且可能因插件干扰而漏包
composer.lock 是权威依赖快照,但不能直接当“清单”用
composer.lock 文件本身是完整、精确、可复现的依赖快照,但它不是为“人眼阅读”设计的。它的 packages 字段里混着 root 包、开发依赖、平台包(如 ext-curl),还包含大量构建元数据(dist、source、transport-options),直接解析容易误判。
典型踩坑:有人用 jq '.packages[] | select(.type != "project")' composer.lock 来过滤非项目包,结果漏掉 require-dev 里的测试工具(它们 type 也是 library);或者把 platform 里的 PHP 版本当成一个“依赖包”统计进去。
- 真正需要锁定语义时,就该用
composer.lock—— 但导出“清单”目的通常是审计、报告或 diff,这时应优先走composer show - 若必须从 lock 解析,务必区分
packages(已安装的 PHP 包)和packages-dev(开发依赖),并跳过platform和platform-dev -
composer validate能确认 lock 是否与 json 同步,但不校验内容是否真实存在 vendor 中
CI/CD 场景下推荐组合命令:先 install 再 show
在 GitHub Actions、GitLab CI 等环境里,光靠 composer show 可能报错:“No composer.lock found”,因为很多流程跳过了 composer install。这时候不能硬凑,得按实际生命周期来。
正确顺序是:确保 composer install --no-interaction --prefer-dist 成功执行后,再跑 composer show -a --format=json。否则你拿到的可能是空列表,或旧缓存结果。
- 加
--no-dev要谨慎:如果清单用途包括安全扫描(如检测phpunit版本),去掉 dev 依赖就会漏报 - 在 Docker 构建中,别把
composer show放在COPY . .之前——vendor 还没生成,命令必然失败 - 若项目用了
path类型仓库(本地路径依赖),composer show仍能正确显示其版本(来自其自身composer.json),但composer.lock里记录的是绝对路径,二者语义不同
依赖清单这事,表面是导出动作,实质是明确“以谁为准”:代码?lock?还是 vendor 目录?选错源头,后面所有分析都偏了。










