composer update --lock 并不安全,它只刷新 lock 文件元信息而不校验 composer.json 的依赖变更,导致锁文件与声明不一致;仅适用于 PHP 版本切换、config/repositories 修改或 lock 格式对齐等特定场景。

为什么 composer update --lock 不如你想象中“安全”
它确实只重写 composer.lock,不下载或安装任何包,但前提是:所有已声明的依赖版本约束在 composer.json 中**没有发生变更**。一旦你改过 require 或 require-dev 的版本号、添加/删减包,composer update --lock 会静默忽略这些改动——它不会报错,也不会同步锁文件,导致 composer.lock 和 composer.json 实际不一致。
- 典型误用场景:本地改了
"monolog/monolog": "^2.10",然后运行composer update --lock,结果锁文件里还是旧版本 - 它只重新解析当前
composer.json的约束 + 当前composer.lock记录的包来源(如packagist.org镜像配置),不校验版本变动 - 适合用在 CI 流水线里快速“固化”当前 lock 文件结构(比如补全
content-hash或更新platform-check字段),但绝不适合替代composer update来响应依赖变更
composer update --lock 真正有用的三个时刻
它不是“偷懒跳过安装”的捷径,而是针对特定元信息刷新的操作。以下情况才该用:
- 刚切换了 PHP 版本(如从 8.1 升到 8.2),需要让 lock 文件里的
platform字段和platform-check值生效,但不想重装全部包 - 修改了
composer.json中的config(如"fxp-asset": false)或repositories,需让 lock 文件记录新的解析上下文 - 团队协作中,别人提交了新版 lock 文件,你本地
composer.json没变,但想强制对齐 lock 文件格式(比如修复缩进、排序或新增plugin-api-version)
替代方案:什么时候该用 composer update --dry-run
如果你真正想要的是“看看更新会装什么,但先不装”,--dry-run 比 --lock 更贴近意图。它会完整走一遍依赖解析流程,输出将要安装/升级的包列表和版本,且能捕获 composer.json 的任何变更影响。
-
composer update --dry-run会告诉你:monolog/monolog将从 2.9.2 升到 2.10.0,phpunit/phpunit将被移除 - 它不写 lock 文件,也不下载包,但会验证所有约束是否可满足——这才是“预检”的正确姿势
- 如果输出里有
Nothing to install or update,说明 lock 文件已是最新;如果有变更,则必须跑真实composer update并提交新 lock
容易被忽略的兼容性陷阱
composer update --lock 在 Composer 2.2+ 中默认启用 lock 文件格式 v2,但老项目若长期没更新,lock 文件可能仍是 v1。此时执行该命令,会悄悄升级 lock 格式——而某些老旧 CI 工具或私有仓库插件可能不兼容 v2 的 packages-dev 结构或 content-hash 算法。
- 检查当前 lock 格式:
head -n 1 composer.lock,v2 是{"_readme"开头,v1 是{"hash" - 若需保持 v1,加
--no-plugins并确保 Composer 版本 ≤ 2.1(不推荐,v1 已废弃) - 更稳妥的做法:在
.composer/config.json里设"lock"→false,彻底禁用自动锁文件生成,改用显式composer update控制节奏










