composer install 仅在无 composer.lock 且有 composer.json 时自动生成锁文件,本质是复现依赖;composer update 才重算版本并更新锁文件,二者核心区别在于是否信任 lock 文件。

composer install 为什么有时生成 lock,有时报错?
它只在一种情况下会自动生成 composer.lock:项目根目录下**完全没有这个文件**,且存在有效的 composer.json。此时 composer install 会退化为先执行依赖解析(等价于 composer update --no-install),再写入锁文件并安装——但这属于兜底行为,不是设计本意。
常见错误现象:No composer.lock file present. Please run "composer install" to generate it. 这句提示本身就有误导性,它实际想让你跑的是 composer update,而不是重复执行 install。
- 正确做法:新项目初始化后,第一件事是运行
composer update,它才真正按语义约束计算版本、校验兼容性、生成带完整哈希和源信息的锁文件 - 如果
composer.json已改但没跑update,composer install会报Lock file is not up to date—— 它不负责更新 lock,只忠实地“照单抓药” - CI/CD 或部署机上永远用
composer install;本地加包、调版本时才用composer update
composer update 和 composer install 的本质区别是什么?
不在字面意思,而在是否信任 composer.lock。一个重算,一个复现。
-
composer update:无视现有 lock 文件(哪怕有),重新解析composer.json中所有约束(如"monolog/monolog": "^2.0"),找当前满足条件的最新兼容版本,覆盖写入composer.lock -
composer install:只读composer.lock,按里面记录的精确版本(如"monolog/monolog": "2.9.1")下载安装,跳过任何版本计算,不联网查包,不解析依赖树 - 误删
composer.lock后直接composer update,等于把整个依赖树“重抽一次签”,可能引入小版本不兼容、安全补丁缺失或静默行为变更
怎么安全地更新 lock 文件而不升级无关包?
别一上来就全量 composer update。它容易连带升级一堆你根本没动过的依赖,放大风险。
- 针对性更新:比如只改了日志组件,就运行
composer update monolog/monolog --with-dependencies,它会更新该包及其直系依赖,其他不动 - 仅刷新 lock 文件格式(如修复缩进、对齐平台字段):用
composer update --lock,它不下载包、不改版本,只重写 lock 文件结构(Composer 2.2+ 默认输出 v2 格式) - 想预览更新影响但不执行?用
composer update --dry-run:它会完整走一遍解析流程,告诉你哪些包要升、哪些要删、有没有冲突,且能验证composer.json变更是否可满足
团队协作中 lock 文件必须提交吗?
必须。不提交 composer.lock,等于把“依赖一致性”交给运气。
- Git 提交它,才能确保开发、测试、生产三端安装的每个包都是同一 commit、同一 shasum、同一 dist URL
-
vendor/永远不要进 Git:体积大、含平台相关二进制(如ext-redis的 so)、Git 无法 diff,还会拖慢克隆 - CI 脚本里严禁出现
composer update,除非你明确要刷新依赖;应始终用composer install --no-interaction --no-progress - 遇到 lock 冲突?别手动编辑,用
git checkout --ours composer.lock或git checkout --theirs composer.lock任选其一还原,再composer install验证是否可装
最常被忽略的一点:lock 文件不是日志,而是带哈希校验的锁定快照。它记录的不只是版本号,还有 dist URL、shasum、source 类型……少一个字段,都可能导致 vendor 安装结果不一致。










