唯一权威来源是composer.lock,导出精确依赖清单用composer show --locked --format=txt > deps-locked.txt,不加--dev仅含生产依赖,加则包含require-dev包;没lock文件会报错。

导出项目环境信息,本质是导出「可复现」的依赖状态,不是抄 vendor 目录、也不是只看 composer.json——唯一权威来源是 composer.lock,它包含每个包的版本、dist 地址、checksum 和 PHP 平台约束。其他所有“导出”命令,都是对它的二次解析,不能替代它本身。
怎么用 composer show --locked 查当前实际安装的包
这个命令直接读 composer.lock,不查 composer.json,也不扫描 vendor/ 目录,所以结果稳定、可预期。
- 没
composer.lock就报错:Could not find package in lock file,这是正常行为,不是 bug - 加
--no-dev可排除require-dev中的包(如 phpunit、phpstan),适合生产环境审计 - 加
--format=json输出结构化数据,字段包括name、version、source、dist,但不含 checksum 或 install-path - 想快速比对两个环境差异?用
composer show --locked --format=json | jq -S . > deps.json,再用diff对比
为什么 composer show(不带 --locked)不可靠
它读的是 vendor/ 目录下的实际文件,一旦有人手动删过子目录、或 composer install 被中断、或用了 --ignore-platform-reqs 跳过检查,结果就和 composer.lock 对不上。
- 常见错误:CI 流水线里跑
composer show生成清单,结果发现本地装的是 monolog/monolog v2.9.3,CI 里却是 v2.10.0——因为 CI 没跑composer install,vendor/是空的,composer show返回空或默认 fallback -
composer show --tree看依赖层级时,如果某个子依赖被平台限制跳过(比如缺 ext-gd),它不会显示缺失,而是静默丢掉整条分支 - 不加
--locked的输出,无法区分哪些是require直接声明的,哪些是间接拉进来的——而安全审计通常只关心顶层生产依赖
如何导出仅含生产依赖的轻量文本清单
用于人工核对、邮件同步或简单审计时,.txt 比 JSON 更友好,但必须确保来源是 --locked + --no-dev。
- 执行
composer show --locked --no-dev --format=txt > prod-deps.txt,输出格式为package/name 3.5.0,每行一个包 - 别用
composer show --no-dev --format=txt:它没加--locked,可能漏掉被锁死但未安装的包(比如刚改完composer.json还没install) - 如果需要带来源类型(
dist或source),用composer show --locked --no-dev --format=json | jq -r '.[] | "\(.name) \(.version) \(.source.type // "dist")"' - 该 txt 文件只是副产品,不能用于重建环境;真正要同步环境,还是得靠
composer.lock+composer install
composer export 是什么,什么时候该用
Composer 2.4+ 新增的 export 命令,不是导出列表,而是生成一个「最小化、可安装」的新 lock 文件,专为审计和离线部署设计。
- 运行
composer export --format=lock --without-dev > composer-prod.lock,输出的 lock 文件里已彻底移除所有require-dev包及其传递依赖 - 生成的
composer-prod.lock可直接被composer install --no-dev消费,也能喂给 Snyk、Dependabot 做漏洞扫描 - 它比手动过滤 JSON 更安全:不会漏掉因 dev 包约束而被间接锁定的生产包版本
- 注意:该命令要求原始
composer.lock已完整解析(即至少成功运行过一次composer install),否则会报Lock file does not contain required packages
最常被忽略的一点:导出命令再全,也救不了没提交的 composer.lock。只要它不在 Git 里,协作中任何“导出”都只是本地快照,毫无意义。确认 composer.lock 是否被跟踪,比选哪个导出命令重要得多。











