composer update 默认不是“更新”,而是丢弃 composer.lock、按 composer.json 重算整棵依赖图,可能引发静默行为变更;应优先用 composer outdated 评估,再谨慎操作并提交 composer.lock。

composer update 默认不是“更新”,是“重算依赖图”
直接跑 composer update 不会安全地升级现有包,而是丢掉 composer.lock,重新读取 composer.json 中所有版本约束,从 Packagist 拉取当前满足条件的最新版——哪怕只是 7.9.1 → 7.9.2,也可能触发底层行为变更:HTTP 超时缩短、日志字段名改名、断言匹配逻辑收紧。这些不会报错,但会在运行时静默出问题。
常见错误现象:composer update 后本地能跑、CI 通过,上线后某个接口超时或日志格式崩了——不是代码写错了,是依赖重算后默认拿了新行为。
- 生产环境禁止无参数执行
composer update - CI/CD 流水线必须用
composer install,否则每次构建拉的版本可能不同,破坏可重现性 - 本地开发想尝新,也应先
git stash或切分支,再操作
只升一个包,但子依赖卡在旧版?用 --with-dependencies
composer update monolog/monolog 默认只更新 monolog/monolog 本身,它依赖的 psr/log 或 symfony/polyfill-php80 仍按 composer.lock 里旧 SHA 安装。这容易导致 PHP 8.2 下类加载失败,或安全漏洞没被连带修复。
正确做法是显式带上依赖链:
-
composer update monolog/monolog --with-dependencies:更新该包 + 它**直接声明**的依赖(如"psr/log": "^1.1") -
composer update monolog/monolog --with-all-dependencies:递归更新整个依赖子图,包括间接依赖(如psr/log的依赖php扩展要求) - 注意:如果其他包硬锁了同一依赖的旧版(比如
laravel/framework锁symfony/event-dispatcher ^5.4),--with-all-dependencies会直接报冲突,而非跳过
想升主版本(如 Laravel 9 → 10)?别指望 update 自动完成
composer outdated 显示 laravel/framework 9.52.15 → 10.38.1,不等于 composer update laravel/framework 就能成功。Composer 会严格检查约束兼容性,而 Laravel 10 要求 php >= 8.1、symfony/console >= 6.3、phpunit/phpunit >= 10 —— 只要其中任一条件不满足,命令立刻退出并报错。
实操路径很明确:
- 先手动改
composer.json:把"laravel/framework": "^9.0"改成"^10.0" - 同步调整平台要求:
"platform": {"php": "8.2"} - 运行
composer why-not laravel/framework:10.*,看哪个包在拦路(常是第三方插件锁死symfony/*) - 确认无阻塞后,再执行
composer update laravel/framework --with-all-dependencies
漏掉 --with-all-dependencies,很可能只升了 laravel/framework,而 illuminate/support 还卡在 9.x,直接报 Class not found。
全局包更新和 Composer 自身升级不是一回事
很多人混淆三件事:composer global update 更新的是你用 composer global require 装的命令行工具(如 laravel/installer、phpunit/phpunit);composer self-update 升级的是 Composer 本体;而项目里的 composer update 管的是 vendor/ 下的运行时依赖。
关键区别:
-
composer global update读的是~/.composer/composer.json,影响所有项目的全局命令,升级前建议先composer global show --direct看哪些是你主动装的 -
composer self-update仅适用于官方安装方式(curl | php),用brew或apt装的必须走对应包管理器,且往往滞后 - 升级 Composer 本体后,务必验证:
composer --version输出不能含snapshot或beta,否则得立刻composer self-update --rollback
最易忽略的一点:PHP 版本升级(如从 8.1 升到 8.2)后,必须重新跑 composer update(哪怕没改 composer.json),否则 composer install 可能因平台不兼容失败——因为 Composer 会按当前 PHP 版本过滤可用包版本,而 composer.lock 里还记着旧版的 SHA。











