composer update在生产环境翻车,因其忽略composer.lock重算依赖,可能引发Class not found、方法签名变更等BC break;必须在开发环境预演并提交lock文件保障部署一致性。

没有“无痛”迁移,只有把破坏性变更(BC break)提前暴露、逐个击破。Composer 本身不执行迁移,它只负责按规则安装——真正决定是否“痛”的,是你项目里那些被升级包悄悄改掉的接口、配置和构造逻辑。
composer update 为什么总在生产环境翻车
因为 composer update 会忽略 composer.lock,重新解析 composer.json 中的约束,拉取满足条件的最新可用版本。哪怕只是 minor 升级(比如 monolog/monolog 从 2.9.0 到 2.10.0),也可能触发:Class not found(自动加载路径失效)、Call to undefined method(方法签名变更)、Failed to open stream(私有包 dist URL 失效)。
- 永远在开发环境运行
composer update --dry-run先看会动哪些包 - 锁定具体版本比用
^更可控:例如composer require monolog/monolog:2.10.0,而非composer update monolog/monolog - 升级前先跑
phpunit --filter=Legacy或自定义测试用例,确认旧调用路径仍能通过 - CI 流水线中禁用
composer update,只允许composer install—— 依赖树必须由composer.lock精确控制
如何识别并处理 BC break
不能靠猜,得看包作者有没有写清楚。重点盯三个地方:CHANGELOG.md 里每个大版本头的「Breaking Changes」小节、GitHub Release 描述、UPGRADE.md(如果存在)。但更关键的是:它们是否把变更映射到你代码里真实调用的位置?
- 查到
OldService::doWork()→NewService::run(),立刻 grep 项目里所有OldService的引用 - 配置项变更必须给完整片段:
"cache_dir"→"cache.path"不够,要写明:"cache": { "path": "var/cache" } - 构造函数参数变化(如
StreamHandler在 Monolog v3 中第二参数不再可选),必须补全,否则 runtime 报错 - 废弃方法(
@deprecated)不会立刻崩,但 Composer 安装时会输出警告;别忽略,它大概率是下个主版本直接删除的信号
为什么 composer.lock 文件必须随 Git 提交
因为它是唯一能保证 composer install 在不同机器上还原出完全一致依赖树的凭证。不提交 composer.lock,等于让每次部署都变成一次盲抽彩蛋。
- 旧服务器上
composer install装的是v2.10.0,新服务器没lock文件,可能装成v2.12.0—— 后者删了一个你正在用的 protected 属性 - Composer 2.x 生成的 lock 文件含
"lock-version": 2,若团队混用 Composer 1 和 2,composer install会直接失败,报错不是警告,是硬拦截 - 私有包(GitLab 私仓、Satis)的
dist.url和source.reference都记录在lock里,缺了就无法下载 - 运行
composer update --lock只更新 lock 文件哈希,不改依赖版本,适合修复因缓存污染导致的校验失败
最常被跳过的一步:升级前没检查 config.platform 是否匹配目标环境。比如 composer.json 里写了 "php": "8.1.0",但新服务器是 PHP 8.3,不加 --ignore-platform-reqs 就卡住——但这不是解法,是掩盖问题。真正的迁移,得从 PHP 版本、扩展、平台约束开始对齐。


















