答案是:composer install --locked 是 CI/CD 中唯一能守住环境契约的确定性操作,它强制校验 composer.lock 存在且合法,缺失或不兼容时立即失败,杜绝 fallback 重算依赖导致的环境漂移。

composer install 不是“装依赖的通用入口”,它是敏捷交付链上唯一能守住环境契约的确定性操作——只要 composer.lock 存在且合法,它就只做一件事:把开发、测试、预发验证过的那套依赖,原封不动搬到新机器上。
为什么 CI/CD 脚本里必须写 composer install --locked
不加 --locked 是最大隐患:一旦 composer.lock 缺失、损坏或与 composer.json 不兼容,Composer 会悄悄 fallback 到按 composer.json 重算依赖,结果不可控。这等于在上线前偷偷改了依赖树。
-
--locked强制校验 lock 文件存在且结构合法,失败直接中断,不自作主张 - CI 中应配合
composer validate --strict和composer install --dry-run提前暴露 lock 同步问题 - 漏掉
--no-dev可能把 PHPUnit 打进生产镜像;漏掉--optimize-autoloader会让类加载慢一倍以上(尤其 APCu 环境)
刚 clone 项目就 composer install 失败?先盯这三处
不是网络或镜像问题,90% 是交付流程断点。
-
composer.lock没提交进 Git —— 它不是“可选文件”,而是环境契约的载体 -
vendor/被错误写进.gitignore,导致 CI 拉不到完整代码树(注意:vendor 绝对不能提交,但 lock 必须提交) -
composer.json里有隐藏空格或换行符(比如"laravel/framework": "10.x-dev "多了个空格),install 阶段不报错,autoload 阶段才炸
composer install 成功 ≠ 应用能跑起来
常见现象:vendor 目录有了,php artisan 却报 Class not found。这不是依赖没装,而是自动加载没生效。
- 检查
vendor/autoload.php是否被正确引入(入口文件里是否写了require __DIR__.'/vendor/autoload.php';) - 运行
composer dump-autoload --classmap-authoritative强制刷新类映射,尤其当你手动增删过src/下的类 - 如果用了自定义 autoload 映射(如 PSR-0 或 classmap),确认路径拼写和命名空间完全匹配,大小写敏感
最常被忽略的细节:lock 文件里记录的是“已验证通过”的精确版本组合,而 composer install 的全部价值,就在于它连一个字符都不改地复现这个组合——不是靠人眼核对,而是靠命令强制执行。一旦跳过这层约束,敏捷迭代就从“可控演进”退化成“随机漂移”。


















