composer update 默认不强制重装,仅更新满足版本约束的包;要真正重装需三步:删 vendor、删 composer.lock、再执行 composer install。

直接说结论:composer update 默认不会“强制重装”,它只更新满足版本约束的包;要真正清掉旧文件、重走安装流程,得组合清理 + 更新命令,否则缓存、vendor残留、lock 文件偏差都会导致行为不符合预期。
为什么 composer update 看起来没刷新?
常见现象是改了 composer.json 里的某个包版本(比如从 "monolog/monolog": "^2.0" 改成 "^3.0"),执行 composer update 后 vendor 里还是 v2.x —— 这不是 bug,是 Composer 的依赖求解逻辑在起作用:它会复用 lock 文件中已记录的兼容版本,只要不违反约束就跳过升级。
- lock 文件存在时,
composer update实际以composer.lock为权威依据,不是composer.json - 如果目标版本已在 lock 中且满足新约束,Composer 认为“无需更新”
- vendor 目录里的文件也不会被自动删干净,旧类、旧配置可能残留
真正强制重装的三步操作
这不是单个命令能解决的事,必须拆成明确动作,每步都有不可替代的作用:
- 删掉
vendor/目录:rm -rf vendor(Windows 用rmdir /s vendor)—— 不清这个,install或update都可能跳过写入 - 删掉
composer.lock:rm composer.lock—— 否则composer install会照着旧 lock 装,根本不管composer.json有没有改 - 重新生成依赖:
composer install(推荐)或composer update --with-all-dependencies(慎用)—— 前者严格按当前composer.json求解并写新 lock;后者虽带--with-all-dependencies,但若没删 lock,仍受旧约束牵制
composer update 加参数的适用场景和陷阱
加参数不是万能钥匙,不同参数解决不同问题,乱用反而更难排查:
-
composer update --force-scripts:只强制运行脚本(如post-install-cmd),不碰依赖树 -
composer update --no-cache:跳过本地包缓存,但不影响 vendor 或 lock 行为 -
composer update --with-all-dependencies:递归更新子依赖,但前提是 lock 文件本身允许升级路径;如果锁死在旧大版本(比如"php": "7.4"),即使你composer.json改成"^8.1",它也不会升 PHP —— 因为 lock 里没这条路径 - 最危险的是
composer update --lock:它会重写 lock 文件但不装 vendor,容易造成 lock 和实际文件不一致
CI/CD 或多人协作时最容易忽略的一点
很多团队在 CI 脚本里写 composer update 就以为“最新了”,但没意识到:如果上一次构建留下的 composer.lock 是旧的,又没做 git clean -fdx 类清理,那这次 update 很可能只是“在旧 lock 上微调”,连主依赖都没动。真正可靠的 CI 步骤是:rm -f composer.lock && rm -rf vendor && composer install —— 三步缺一不可,少一步都可能让环境漂移。











