直接改composer.json后运行update最危险,因会强制重算依赖图、跳过兼容性验证、掩盖平台冲突,导致ci失败;应先备份lock、删vendor、用install生成新lock并验证。

直接改 composer.json 然后跑 composer update 是最危险的升级起点——它会跳过兼容性验证、绕过锁文件比对、掩盖平台约束冲突,90% 的 CI 失败都源于这一步。
为什么不能直接改 composer.json 后运行 update
Composer 不是“改完就生效”的配置文件工具。composer.json 只是声明意图,真正决定装什么的是 composer.lock。直接改 composer.json + update 会强制重算整个依赖图,可能触发:
- 隐式降级:某个间接依赖因新约束被回退到不兼容旧版(比如
psr/log从 3.x 退回 1.x) - 平台误判:PHP 版本或扩展限制(如
ext-gd)在update过程中被忽略,直到vendor/autoload.php加载时报错 - 插件失效:自定义 installer 或事件监听器(如
pre-autoload-dump)因依赖版本突变而跳过执行
本地测试必须走 install 而非 update
目标是验证“新声明”能否在当前环境生成可运行的 vendor/,而不是让 Composer 自动调和新旧状态。正确流程是:
- 备份原
composer.lock(例如重命名为composer.lock.bak) - 修改
composer.json中目标包的版本约束(如"guzzlehttp/guzzle": "^7.8"→"^8.0") - 删除
vendor/目录(不能只删部分子目录) - 运行
php -d memory_limit=-1 composer install --no-interaction(加--no-interaction避免卡在交互提示) - 检查输出是否有
Root package requires ... but it is not installable或Package x is abandoned
对比 lock 文件才能发现真实变更
composer install 成功后,新生成的 composer.lock 和旧版差异才是关键证据。重点关注:
-
packages和packages-dev下目标包的version、source.type(应为"zip",不是"git"或"path")、dist.shasum -
platform字段是否仍匹配你部署环境的 PHP 版本(如"php": "8.1.26") - 是否有意外新增或消失的包(尤其
psr/*、symfony/polyfill-*类轻量依赖)
测试失败时怎么快速回滚
别手动改 composer.json 或删 lock 行——残留字段会导致下次 install 仍拉错版本:
- 先执行
git checkout composer.lock.bak -- composer.lock(还原 lock) - 再运行
composer install(重建 vendor) - 确认测试套件 green 后,再针对性调整
composer.json,比如加"--with-all-dependencies"或显式 require 传递依赖
最容易被忽略的是:composer install 成功不代表自动加载就通——务必跑一次 composer dump-autoload --no-dev 并检查 vendor/autoload.php 是否能正常 require 你的核心类,否则 CI 里 --no-dev 模式下第一行就崩。











