composer.lock 是 PHP 项目依赖的“事实快照”,非缓存文件;删它、不提交或 CI 跳过即放弃环境一致性。install 必须读 lock 才能精确还原版本、SHA256 和依赖树,否则退化为不可控 update。

composer.lock 不是缓存文件,它是 PHP 项目依赖的“事实快照”——删它、不提交、或在 CI 里跳过它,等于主动放弃环境一致性。
composer install 为什么必须读 composer.lock
因为 composer install 的设计目标就是「精确还原」:它只看 composer.lock 里写的版本号、SHA256 校验值、完整依赖树,完全忽略 composer.json 中的 ^ 或 ~ 版本约束。没有这个文件,composer install 就会退化成 composer update,从头解析整个依赖图。
常见错误现象包括:
-
Your requirements could not be resolved to an installable set of packages.—— 实际是 lock 缺失或过期,但报错误导人去改composer.json - 本地能跑,CI 构建失败,报
Class not found—— 某个子依赖(如psr/http-factory)在无 lock 时被装成了 v2,而代码只兼容 v1 -
composer install --no-dev在生产环境出问题 —— 不是因为 dev 依赖没装,而是 lock 文件本身没包含平台一致性配置,导致某些包被静默跳过
哪些修改必须触发 composer update 并提交新 lock
只有当 composer.json 中影响依赖解析逻辑的字段变更时,才需要运行 composer update 并提交更新后的 composer.lock。
需要更新 lock 的典型场景:
- 修改
require或require-dev中的包名或版本约束(例如把"guzzlehttp/guzzle": "^7.0"改成"^8.0") - 增删包(
composer require foo/bar或手动删require条目) - 调整
config.platform(如统一设为"php": "8.1.0") - 变更
minimum-stability或启用prefer-stable
不需要更新 lock 的情况:
- 只改了
autoload、scripts、name、description等字段 - 只运行
composer dump-autoload或composer clear-cache
团队协作中 composer.lock 冲突了怎么安全解决
lock 文件是完整依赖图的序列化结果,不能像普通 JSON 那样手动合并。任意删行、凑合保留某一方内容,都会导致后续 composer install 失败或依赖不一致。
正确做法是放弃文本冲突解决,靠 Composer 重建:
- 先用
git checkout --ours composer.lock或git checkout --theirs composer.lock任选其一恢复文件(推荐选目标分支,如main) - 删除
vendor/目录(避免残留旧包干扰) - 运行
composer install—— 如果当前composer.json和所选 lock 不匹配,会报错Your lock file does not contain a compatible set of packages,此时应先git pull拉最新代码,再重试 - 若需同步他人对依赖的修改,直接运行
composer update --lock(不升级包,只重写 lock)
CI/CD 流水线里如何校验 lock 是否过期
不能靠人眼检查 diff,得让机器自动判断:当前 composer.json 是否与 composer.lock 一致。
实操方式:
- 在 CI 脚本开头加一行:
composer validate --strict—— 它会检查 lock 是否覆盖了 json 中所有 require/require-dev 条目,并验证 content-hash - 更严格的做法是运行
composer install --dry-run,它会模拟安装过程,遇到不匹配立即退出并报错 - 如果 CI 报
Lock file is not up to date with composer.json,说明有人改了 json 却没跑composer update提交新 lock,这是最隐蔽的协作断裂点
真正难的不是命令怎么写,而是所有人得明白:composer.lock 不是生成物,它是和 composer.json 平级的源码 —— 改了依赖却不提交 lock,就像改了 PHP 类却不提交 .php 文件。











