composer.lock是项目依赖的唯一可交付快照,必须提交至Git;它锁定精确版本、dist校验值、platform约束等关键信息,缺失时composer install将退化为不可控的update,导致环境不一致与构建失败。

composer.lock 就是导出目标,不是“要导出的东西”,而是“唯一可交付的依赖快照”——所有所谓“导出依赖列表”的操作,本质都是对它的读取或格式转换。
为什么不能用 composer show 替代 composer.lock
很多人想用 composer show --format=json 或 composer show --locked 生成一个“可复现安装”的清单,但这是错觉。这些命令输出的是只读快照,不含以下关键信息:
-
dist下载地址和shasum校验值(无法验证包完整性) - 平台约束(如
"php": ">=8.1.0")在 JSON 输出里不参与解析逻辑 - 私有仓库源配置、插件行为、
autoload映射等上下文全丢失
更关键的是:composer install 完全不认这些输出,它只读 composer.lock。你导出的 JSON 或 TXT 文件,连 composer require 都没法消费。
composer show --locked 的真实用途和陷阱
这个参数(Composer 2.5+)确实让 composer show 读取 composer.lock 而非 composer.json,但它仍是展示工具,不是构建工具:
- 加
--no-dev可过滤掉require-dev包,适合生成生产环境审计清单 - 用
--format=txt输出含包名、版本、源类型、哈希值,比--format=short更完整 - 但若项目没运行过
composer install或vendor/已损坏,--locked仍可能报Could not find package in lock file - 它不校验当前 PHP 环境是否满足
platform字段,而composer install会直接失败
Docker 和 CI 中漏掉 composer.lock 的后果
很多构建失败不是因为命令写错,而是因为文件没传全:
- Dockerfile 里只
COPY composer.json .,没COPY composer.lock .→composer install报错并退化为update行为 - CI 脚本未检查
test -f composer.lock→ 构建时版本漂移,某天突然monolog升到 3.x,日志格式变更导致告警误报 - Git 提交漏了
composer.lock,或把它加进了.gitignore→ 团队成员composer install结果各不相同
真正该做的不是“导出”,而是确保 composer.lock 在每次 composer update 后被 git add 并提交——它不是中间产物,是项目契约的一部分。
备份和迁移时最容易忽略的三个条件
单独拷贝 composer.lock 文件毫无意义,还原依赖必须同时满足:
-
composer.json必须存在且与composer.lock的content-hash匹配,否则composer install拒绝执行 -
vendor/目录必须为空或不存在,否则旧包残留会导致 autoloader 加载冲突 - 当前 PHP 版本和扩展(如
ext-mbstring)必须满足composer.lock顶部platform字段声明,否则报Your lock file does not contain a compatible set of packages
这些条件不靠任何“导出命令”保障,只靠工作流规范和自动化检查。











