composer install 不生成 composer.lock 是因它仅在已有锁文件时安装依赖;无锁文件时静默退出,须先用 composer update 生成锁文件并提交至 git。

composer install 为什么没生成 composer.lock
根本原因:你运行的是 composer install,而它只在已有 composer.lock 时才生效;没锁文件时它啥也不干,也不会自动生成——这是设计行为,不是 bug。
常见错误现象:composer install 报错 “No composer.lock file present” 或静默退出,vendor/ 为空,依赖没装。
- 正确做法是先跑
composer update(或composer install --no-lock,但不推荐)来生成初始锁文件 -
composer update会读composer.json、解析最新兼容版本、写入composer.lock并安装依赖 - 团队协作中,
composer.lock必须提交进 Git,否则每人composer install结果可能不一致
共享 lock 文件时哪些字段最关键
composer.lock 不是纯快照,它包含两层信息:顶层的 packages(生产依赖)和 packages-dev(开发依赖),还有 content-hash 和 platform 配置。
容易踩的坑:有人删了 platform 段或手动改 content-hash,导致 composer install 失败或跳过校验。
-
content-hash是composer.json内容的哈希值,只要 JSON 有改动(哪怕空格)、没重跑update,install 就会拒绝执行 -
platform记录 PHP 版本、扩展等,用于满足require中的php或ext-xxx约束;不同环境 PHP 版本不一致时,lock 文件可能无法复现 - 不要手动编辑
composer.lock;所有变更都应通过composer update xxx或composer require xxx触发重写
CI/CD 或 Docker 构建中怎么确保 lock 文件生效
很多构建失败,其实只是因为用了 composer install 却忘了检查 lock 文件是否存在、是否被 .gitignore 排除,或者用了错误的命令顺序。
典型错误:Dockerfile 里先 COPY composer.json .,再 RUN composer install,但没 COPY composer.lock —— 这会导致 install 跳过,实际执行的是 update 行为,破坏可重现性。
- Dockerfile 中必须
COPY composer.lock composer.json ./,且composer.lock在composer.json之后 COPY(否则 content-hash 校验失败) - CI 脚本里加一句
test -f composer.lock || { echo "Missing composer.lock"; exit 1; },早发现遗漏 - 用
composer install --no-interaction --prefer-dist --optimize-autoloader,避免交互、加速下载、减少 autoload 开销
composer update 后 lock 文件变大、diff 很多怎么办
这不是异常,是正常现象。Composer v2+ 默认启用 lock 的完整包信息(包括 dist URLs、shasum、source refs),比 v1 更精确也更冗长。
性能影响几乎为零,但 diff 噪声大,容易掩盖真实变更。关键是别误判“改了很多=升级了很多”。
- 看
packages数组里name和version字段变化,这才是真正升级/降级的包 - 如果只改了 dev 依赖,
packages-dev变动是预期的;生产环境部署应确保只含packages - 不用刻意压缩 lock 文件——它不是给人读的,是给 Composer 解析用的;Git 也能高效处理这类结构化文本
最常被忽略的一点:composer.lock 里的 platform-check 默认开启,如果本地 PHP 版本和目标环境不一致,即使 lock 文件存在,install 也可能失败——得关掉或对齐环境。









