应执行 composer update --lock 重建 lock 文件,因其按 composer.json 重算哈希与依赖,不依赖已冲突的旧 lock;手动修改或保留合并标记必致解析失败、校验不通过或运行时异常。

手动改 composer.lock 不是“省事”,而是直接绕过 Composer 的依赖契约机制,99% 的线上 Class not found、哈希校验失败、CI 构建不一致都源于此。
为什么改完 composer.lock 会触发 Invalid argument supplied for foreach()
这不是 PHP 报错,是 JSON 解析失败的表象。Composer 在读取 composer.lock 前不做语法校验,但一旦遇到非法结构(比如你删了某个逗号、改了缩进、漏掉一个 }),json_decode() 就返回 null,后续代码对这个 null 做 foreach 就崩了。
常见诱因:
- 用文本编辑器手动合并 Git 冲突时,残留
<<<< HEAD或=======标记 - 用在线 JSON 美化工具处理后,字段顺序/换行符被重排,导致
content-hash失效 - 只改了
"version": "2.9.1",但没同步更新同包下的"dist": {"sha256": "..."}字段
composer update --lock 和删 lock 后 composer install 的本质区别
前者是“重写快照”,后者是“放弃快照、重新求解”。这是最关键的分水岭。
composer update --lock:
- 不访问 packagist,不下载任何包,不碰
vendor/ - 只根据当前
composer.json+ 已安装包状态,生成合法、结构完整、哈希匹配的新composer.lock - 输出里应看到
Lock file operations: 0 installs, 0 updates, 0 removals(说明只是刷新快照)
删 composer.lock 后跑 composer install:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- Composer 发现无锁文件,自动退化为
composer update行为 - 它会重新解析所有
^/~约束,可能把guzzlehttp/guzzle从7.8.0升到7.9.0,或把symfony/polyfill-php81换成polyfill-php82 - 结果不可控,且不会提示你——它静默生成新 lock,你以为“装上了”,其实已漂移
Git 冲突时,为什么不能用 git checkout --ours 保留某一方的 lock
因为 composer.lock 不是独立配置,它必须和 composer.json 语义对齐。强行保留某方 lock,等于让依赖快照和源约束脱钩。
后果很具体:
- 如果
--ours保留的是旧 lock,但对方composer.json新增了"phpunit/phpunit": "^10.0",你composer install会失败:找不到该包 - 如果
--theirs保留的是新 lock,但你本地composer.json还没合并那条 require,install 会跳过该包,vendor 缺失关键工具 - 哪怕侥幸通过,
content-hash与composer.json实际内容不匹配,下次有人composer install就会收到The lock file is not up to date警告
真正该操作的地方永远是 composer.json,不是 composer.lock
想锁死某个包?在 composer.json 的 require 里写死三位版本:"monolog/monolog": "2.9.1",然后运行 composer update monolog/monolog —— 这才是唯一能被 Composer 正确识别并持久化的锁定方式。
验证是否生效,别看文件,用命令:
-
composer show monolog/monolog→ 输出必须是2.9.1 -
composer update --dry-run monolog/monolog→ 应显示Nothing to install or update - 打开
composer.lock搜索monolog/monolog,确认"version"字段是"2.9.1",且"dist"下的sha256非空
复杂点在于:lock 文件不是“版本列表”,它是整棵树的哈希快照。哪怕你只改了一个包的版本,Composer 也得重算所有子依赖的哈希、重排 packages 数组顺序、更新 content-hash —— 这些全由它自己完成,人不该插手。

















