composer.lock是php项目依赖的“部署契约”,非缓存文件;它通过packages、packages-dev和content-hash字段精确锁定版本、哈希值与依赖树,确保本地、ci与线上环境完全一致;应用类项目必须提交,库项目则不应提交。

composer.lock 不是缓存文件,它是 PHP 项目依赖的“部署契约”——没它,composer install 直接失败;有它,才能保证你本地跑通的代码,在 CI 和线上也一定跑通。
为什么 composer install 会报 “No composer.lock file present”
这不是提示你“该生成一个”,而是明确告诉你:当前流程已中断。composer install 的设计定位就是「还原」,它只读 composer.lock,从不解析 composer.json 中的版本约束(比如 "^2.0")。
- 新项目首次初始化,必须运行
composer update(不是install),它才会根据composer.json计算依赖并写入composer.lock - 误删
composer.lock后执行composer install,错误信息里建议你 run "composer install" 是误导;正确做法是composer update - CI/CD 脚本中若用
composer install却没提供composer.lock,等同于跳过一致性保障,部署结果不可预测
composer.lock 里真正决定安装行为的字段有哪些
打开文件,别只搜 "version"。关键字段其实就三个区块:
-
packages和packages-dev:每个包的精确版本(如"2.9.2",不是"^2.0")、dist.shasum(校验包完整性)、source.reference(Git commit hash,用于 source 类型安装) -
content-hash:由composer.json内容生成的哈希值;如果改了composer.json却没运行composer update,这个值就不匹配,composer install会警告但不阻止(取决于配置) - 没有
"lock version"字段,也不需要;Composer 2.x 的 lock 格式与 1.x 不兼容,但文件本身无显式版本标识,升级 Composer 后首次update会自动重写格式
团队协作中哪些操作必须提交 composer.lock
不是“所有变更都要提交 lock”,而是只有影响依赖解析的变更,才需配套更新并提交 composer.lock:
- 修改
composer.json中的require、require-dev、platform、minimum-stability或prefer-stable - 添加或删除某个包(哪怕只是
composer require phpunit/phpunit) - 运行
composer update vendor/package后,composer.lock必须全量提交——即使只改了一个包,整个依赖树可能已重算,其他包版本也可能被动变更
应用类项目(如 Laravel 网站、Symfony API)必须提交 composer.lock;库项目(供别人 require 的包)则不应提交——它的依赖应由下游决定。
多人协作时 composer.lock 冲突了怎么办
冲突本身不可怕,可怕的是随便选一边合并。composer.lock 是完整依赖图的序列化结果,手动删行或凑合合并大概率导致依赖不一致或安装失败。
- 先
git checkout --theirs composer.lock或git checkout --ours composer.lock(任选其一还原) - 删掉
vendor/目录,确保干净 - 运行
composer install——它会基于当前composer.json和刚恢复的 lock 校验并生成新 lock - 如果提示
"Your lock file does not contain a compatible set of packages",说明composer.json已被他人修改,此时应先git pull拉取最新,再composer install
真正容易被忽略的是:锁文件不是“记录你装过什么”的日志,而是声明“所有环境必须装一模一样的东西”的契约;一旦破坏,修复成本远高于预防——比如某次未提交的 update,可能让线上突然出现 Class not found,而回溯时根本找不到对应 commit。











