composer install 必须依赖 composer.lock,因其设计目标是“原样还原”而非“解析安装”,仅按 lock 文件中写死的版本号、sha256、dist url 和完整依赖树执行,忽略 composer.json 中所有版本约束;缺失时新版 composer 直接报错“command 'install' is not defined”,旧版则静默失败导致 vendor 错乱。

composer install 为什么死活要 composer.lock
因为 composer install 的设计目标就不是“装满足条件的最新版”,而是“原样还原”。它压根不解析 composer.json 里的 ^2.0 或 ~3.5,只认 composer.lock 里写死的版本号、dist URL、SHA256 校验值和完整依赖树。没有这个文件,命令直接拒绝执行——新版 Composer(v2.5+)会报 Command "install" is not defined,旧版可能静默失败但 vendor/ 内容必然错乱。
常见错误现象:
- CI 构建报
Class 'Symfony\Component\HttpClient\HttpClient' not found,本地却能跑 - 同事
composer install后guzzlehttp/guzzle是7.8.1,你的是7.9.0,但两人都没动过composer.json
原因只有一个:composer.lock 没提交、被误删,或被 .gitignore 忽略了。此时 composer install 会退化为隐式 composer update,整个依赖图重算,结果不可控。
lock 文件冲突了,别手改,用 Composer 重建
composer.lock 不是普通配置文件,它是整个依赖图的完整序列化快照。手动删几行、保留“这边的”或“那边的”字段,大概率导致依赖不一致甚至安装失败。
正确做法是放弃冲突解决,靠 Composer 重建:
- 运行
git checkout --ours composer.lock或git checkout --theirs 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。
CI/CD 里怎么写 composer install 才安全
CI/CD 脚本里只允许出现这一条标准写法:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
composer install --no-dev --optimize-autoloader --no-interaction --no-progress
说明:
-
--no-dev:跳过require-dev里的包(如 PHPUnit、PHPStan),避免把开发工具打进生产镜像 -
--optimize-autoloader:生成扁平化类映射(vendor/composer/autoload_classmap.php),提升自动加载性能,尤其对 APCu 有效 -
--no-interaction和--no-progress:禁用交互与进度条,适配无终端环境
绝对不要加 --ignore-platform-reqs 或 --force —— 它们掩盖的是真实环境缺陷(比如 PHP 版本低于锁文件中某包要求的最低版本),不是问题本身。脚本里混进 composer update,上线那一刻就等于放弃版本控制权。
什么改动必须触发 composer update 并提交新 lock
composer.lock 只对影响依赖解析逻辑的变更敏感。改了就不管,会导致本地能跑、CI 报 Class not found 或行为漂移。
必须运行 composer update 并提交新 composer.lock 的场景包括:
- 修改
require或require-dev中的包名或版本约束(如把"guzzlehttp/guzzle": "^7.0"改为"^8.0") - 增删包(
composer require foo/bar或手动编辑composer.json) - 调整
config.platform、minimum-stability或启用prefer-stable
而改 autoload、scripts、description 这类字段,完全不影响依赖树,不需要碰 lock 文件。
真正容易被忽略的是:lock 文件不是“生成一次就完事”,它是每次依赖变更的强制契约载体;一旦缺失或未同步,所有环境一致性承诺就失效了——不是“可能出问题”,是“一定出问题”,只是时间早晚而已。










