直接看git diff --no-index lock.before composer.lock | grep 'version\|source',重点关注主版本号跳变和source来源变更。

怎么看 composer update 实际改了哪些包
直接运行 composer update 不加参数,等于放弃控制权——它会重算整张依赖图,连 phpunit/phpunit、symfony/var-dumper 这类开发依赖都可能升到不兼容版本,测试直接挂掉,甚至导致 autoloader 失效。真正该看的不是命令输出,而是 composer.lock 差异。
升级前先备份当前 composer.lock(比如存为 lock.before),升级后再执行:
git diff --no-index lock.before composer.lock | grep 'version|source'
重点关注带 "version" 字样的行,特别是主版本号跳变(如 "version": "2.12.0" → "version": "3.0.0");"source" 变动则说明底层 Git commit 或 ZIP 包来源已不同,可能含未发布补丁或 fork 分支。
哪些包升级必须查变更日志
不是所有包都一样危险。真正要盯紧的是这几类:
-
laravel/framework、symfony/*、doctrine/orm:框架/核心运行时,主版本变更常伴随生命周期钩子、事件签名、配置结构的破坏性改动 -
guzzlehttp/guzzle、monolog/monolog、phpunit/phpunit:被大量直接调用的工具库,API 变更会立刻暴露在业务代码里 - 任何在
composer show输出中 PHP 版本约束窄于当前环境(如要求^8.0但你已升到 8.3)且长期未维护的包 - 带
!标记的包——composer outdated会标出主版本可升但未升的,这类最易踩坑
查日志别只翻 GitHub Releases,优先看官方 UPGRADING.md 或 UPGRADE-*.md 文件,它们比 Changelog 更聚焦 breaking changes。
升级后怎么快速验证是否真“稳”了
光跑 phpunit 不够,很多问题藏在边缘路径里。升级后必须立刻做三件事:
- 检查日志:
tail -n 50 storage/logs/laravel.log(Laravel)或var/log/dev.log(Symfony),重点搜Deprecated:和Warning:——这是下个主版本就删的信号 - 验证自动加载:运行
composer dump-autoload -o,再试php -r "echo class_exists('AppHttpControllersHomeController') ? 'ok' : 'fail';",排除 PSR-4 映射断裂 - 抓 HTTP 响应头和状态码:某些框架升级后默认开启 CSP、修改了
X-Powered-By或强制 HTTPS 重定向,前端可能因此报 CORS 或 301 循环
冲突卡住时为什么不能直接加 --ignore-platform-reqs
遇到 Your requirements could not be resolved,第一反应不是删 vendor 或硬加 --ignore-platform-reqs。这个参数只是屏蔽错误,不解决根本矛盾。
正确做法是用 composer why-not vendor/package:3.0.0 定位谁在阻止升级,再结合 composer show vendor/package 看当前可用版本范围。常见原因包括:
- 你当前
composer.json锁死了该包的版本范围(如^2.5),而你想装的3.0不在此范围内 - 另一个已安装包(如
monolog/monolog)显式要求了更低版本的共用依赖(如symfony/polyfill-php80) - PHP 版本约束冲突:某个依赖声明
"php": "^8.0",但你的 CLI 是 8.3,而它的最新版还没适配
真正难处理的从来不是版本号本身,而是多个包对同一底层依赖的隐式拉扯——这种冲突往往不会报错,只会让某段逻辑在特定条件下静默失效。











