composer install 严格遵循 composer.lock 安装确定版本,用于日常协作与部署;composer update 忽略 lock 文件重新解析依赖,仅应在开发阶段有明确目标并验证后使用。

composer install 和 composer update 的本质区别,就一条:**是否尊重 composer.lock 文件**。
前者照着锁文件“照单抓药”,后者扔掉锁文件“重新配药”。用错命令,轻则装错版本跑不起来,重则线上崩了还查不出原因。
什么时候该用 composer install?
这是你日常协作和上线部署时**唯一该用的命令**。
- 团队新人克隆项目后,直接运行
composer install—— 它会严格按composer.lock里写死的版本号安装,所有人得到一模一样的vendor/ - CI/CD 流水线、Docker 构建、生产服务器部署,必须用
composer install --no-dev(跳过开发依赖) - 本地改完代码想快速复现线上环境?删掉
vendor/后只跑composer install,不碰composer.json里的约束 - 如果项目没有
composer.lock,install会退化成首次解析,自动生成锁文件——但这属于例外,不是常态
为什么不能在服务器上乱跑 composer update?
它不是“升级工具”,而是“依赖重算引擎”。
- 它会忽略
composer.lock,联网重新求解整个依赖树,可能把monolog从2.9.1升到3.0.0—— 而 v3 已经移除了你正在用的Monolog\Logger::addInfo()方法 - 执行一次
composer update,composer.lock必然被重写,且 diff 可能长达几百行,你根本没法肉眼判断哪些包变了、为什么变 - 它默认会更新所有包(包括
require-dev),哪怕你只想修一个安全漏洞;必须加--with-dependencies或限定包名,比如:composer update symfony/http-kernel --with-dependencies
- 耗时远高于
install:要解析约束、查 packagist、比对版本、解冲突、下载新 zip、验证哈希……部署窗口等不起
composer update 的正确打开方式
它只应在开发阶段、有明确目标、且做好验证的前提下使用。
- 想升级某个包到新版?先确认
composer.json里它的版本约束是否允许(比如从"^1.2"放宽到"^2.0"),再运行composer update vendor/package-name - 修复已知 CVE?查 symfony security advisories 或 FriendsOfPHP,找到受影响包和修复版本,再针对性更新
- 升级后必须跑测试:
vendor/bin/phpunit、phpstan、接口回归,甚至手动点一遍关键路径 - 更新完成并验证通过后,立刻提交新的
composer.lock到 Git —— 这是让队友和线上环境同步变更的唯一方式
容易被忽略的关键细节
很多人以为 “有 composer.lock 就安全”,其实不然。
-
composer install不校验composer.lock是否和composer.json逻辑一致。如果你删了composer.json里某个包但忘了删lock里的记录,install照装,但 Composer 不报错 -
composer update默认会更新require-dev,而生产环境不该装这些。上线前务必用composer install --no-dev,别指望update时加参数能“安全降级” - Git 提交时漏掉
composer.lock,等于没锁 —— 所有后续install都变成首次解析,结果不可控
install,PR 检查强制要求 composer.lock 和 composer.json 同步变更,生产镜像构建禁止出现 update 字样。









