composer install是唯一安全选项,因它严格按composer.lock安装精确版本、commit hash及平台要求,不解析不升级;而composer update会忽略lock文件重算依赖树,易引发线上行为漂移。

生产环境不能直接运行 composer update,必须用 composer install 配合已提交的 composer.lock。 这不是流程建议,是防止线上行为漂移的底线。
为什么 composer install 是唯一安全选项
它只读取 composer.lock 中记录的精确版本、commit hash、PHP 扩展要求和平台配置,不做任何重新解析。而 composer update 会忽略 lock 文件,按 composer.json 的约束重新协商整个依赖树——哪怕只是补丁升级,也可能触发底层行为变更(如 Guzzle 默认超时从 30s 缩短为 5s),且无法回溯。
- CI/CD 流水线中必须写死
composer install --no-dev --optimize-autoloader --prefer-dist --no-interaction - 如果部署脚本里出现
composer update(无论是否带参数),都应立即下线并审计 -
composer.lock必须提交到 Git,且每次git pull后都要执行composer install,不能跳过
更新前必须验证的三件事
真正要“更新”生产依赖,本质是先在开发/预发环境完成变更,再把新 lock 文件推上线。这个过程必须卡住三个检查点:
- 运行
composer outdated --direct:确认哪些显式依赖有新版,尤其关注标有[security]的行,以及主版本跳变(如symfony/console 5.4 → 6.4) - 检查
composer show:确认当前安装版本与composer.json中声明的约束是否一致,避免因config.platform导致outdated漏报 - 执行
composer check-platform-reqs:验证 PHP 版本、扩展(如ext-mbstring)是否满足新依赖要求,不通过就别往下走
composer update 在哪能用、怎么用
它只允许出现在非生产环境,且必须严格限定范围。无参数的 composer update 是运维事故高发操作,真实维护中只接受以下写法:
- 升一个包:
composer update guzzlehttp/guzzle:^7.5(明确指定版本范围,而非仅包名) - 升一组相关包:
composer update laravel/framework illuminate/*(避免漏掉配套组件) - 加
--dry-run预览变更:composer update monolog/monolog --dry-run,先看它打算改什么再决定是否执行 - 禁用
--with-dependencies:Composer 2.2+ 已移除该选项,若旧脚本还保留,会报错或行为异常
部署时最常被忽略的细节
很多人以为 composer install 跑完就万事大吉,但线上类加载失效、性能下降或静默报错,往往出在这些地方:
- 没加
--optimize-autoloader:导致 PSR-4 自动加载慢几倍,尤其在大量命名空间的项目里 - 忘了
composer dump-autoload -o:vendor 更新后,若项目含自定义 PSR-4 映射,必须重建优化映射,否则类找不到 - 误用
--ignore-platform-reqs:本地调试可临时绕过 PHP 版本检查,但一旦进到composer.lock,就可能让生产环境装上根本不兼容的包 -
composer.lock中混入平台字段变更(如php版本号被意外修改):用composer validate可快速识别,但多数人跳过这步











