composer.lock 是 composer install 的精确执行清单,记录了所有依赖包的版本、dist 归档哈希等确定性信息,必须提交至 Git 以保证环境一致性。

composer.lock 是什么,为什么不能删
它不是缓存,也不是日志,而是 composer install 的精确执行清单。删了再跑 composer install,会按 composer.json 重新解析依赖树,很可能装上新版——哪怕你没改过 composer.json。
常见错误现象:composer install 在 CI 上失败,或本地能跑、测试环境报 Class not found,八成是 composer.lock 没提交,或被误删后重建了。
- 只要项目有协作或部署流程,
composer.lock必须提交到 Git - 手动修改
composer.json后,必须运行composer update(而非install)来更新 lock 文件 -
composer install会严格按composer.lock安装,忽略composer.json中的版本约束符(如^2.0)
composer update 和 composer install 到底该用哪个
一句话:日常开发加依赖、升大版本用 composer update;CI、上线、同事拉代码后初始化环境,只用 composer install。
容易踩的坑:composer update 默认更新全部包,哪怕你只改了一个 require,也可能连带升级 symfony/console 或 phpunit/phpunit,引发兼容性断裂。
- 只更新某包:用
composer update vendor/package-name,不加空格、不加引号 - 想锁死 PHP 版本影响:在
composer.json里写"config": {"platform": {"php": "8.1.10"}},否则update可能选错兼容版本 -
install时若无composer.lock,会退化为update行为——这很危险,CI 脚本里应加检查:test -f composer.lock || exit 1
lock 文件里 version 字段到底是包版本还是 dist 版本
是 dist 归档的版本,不是 VCS 分支或 tag 名。比如 "version": "v3.5.2" 对应的是 GitHub Release 打包的 zip,不是 git checkout v3.5.2 的结果。
这意味着:即使包作者删了 tag、重推 commit,只要 dist URL 没变、hash 没变,composer install 就不会感知——这也是 lock 文件能保证可重现的关键。
- dist 的
sha256哈希值在 lock 文件里叫"dist": {"sha256": "..."},校验失败会直接中止安装 - 如果用
--prefer-source,lock 文件里"source"字段生效,此时校验的是"reference"(即 commit hash),但 CI 环境不建议这么干——慢且不稳定 - 别手改 lock 文件里的
version或sha256,Composer 不认,下次update会被覆盖
为什么有时 composer install 会跳过某些包
不是漏装,是命中了 "platform-check": false 或平台配置冲突。最典型的是 PHP 版本不匹配,或者扩展缺失(如 ext-gd),Composer 会静默跳过那些声明了 ext-xxx 依赖的包。
现象:装完没报错,但运行时报 Call to undefined function imagecreatefrompng(),查 composer show 却发现 intervention/image 显示已安装——其实它根本没进 vendor。
- 运行
composer install --ignore-platform-reqs能绕过检查,但只是掩耳盗铃,上线前务必还原 - 正确做法是在
composer.json的"config"下设"platform",显式声明目标环境能力,让update阶段就暴露问题 -
composer why-not vendor/package可诊断具体哪个平台要求挡住了安装
lock 文件真正难搞的地方不在格式,而在它把「依赖决策」和「环境假设」全压缩进一个 JSON 里——改一行 composer.json,可能触发整个依赖图重算;换一台机器,可能因 PHP 模块差异让 lock 里某些包彻底失效。盯住 dist.sha256 和 platform 配置,比背命令重要得多。










