composer outdated 默认只显示符合 composer.json 版本约束且有新稳定版的包;无输出常因版本写死、使用 dev-main、composer.lock 滞后或 minimum-stability 限制,需用 --all、--direct 等参数排查。

直接运行 composer outdated 就能列出当前项目中「符合你现有版本约束」且有新稳定版的包——但它不是“所有新版”,更不是“所有该升的”。输出为空不等于安全,标红也不等于必须立刻升级。
为什么 composer outdated 没输出,但明明有新版?
常见原因不是没更新,而是它根本“看不见”:
- 你的
composer.json里写死了版本,比如"monolog/monolog": "2.8.0"(没^或~),Composer 认为这已是最终决定,不纳入“可更新”范畴 - 用了
dev-main、dev-develop这类开发分支,它默认跳过检查——加--all才强制显示 -
composer.lock长期没更新(比如 CI 没跑composer install),outdated 基于 lock 文件比对,结果自然滞后 - 设置了
"minimum-stability": "stable",而新版本是beta或rc,直接被过滤
composer outdated 标红的包到底意味着什么?
标红 ≠ 有补丁更新,而是提示存在语义化版本意义上的「非补丁级变更」:次版本(如 2.1.0 → 2.2.0)或主版本(如 2.9.0 → 3.0.0)。这类更新更可能含 BC break。
- 加
--minor-only可只看次版本更新,跳过主版本干扰 - 加
--patch-only(Composer ≥ 2.5)才真正聚焦补丁修复 - 标红包旁边若显示
constraint: ^2.5,说明当前约束允许升级;若显示None,说明已装版本其实超出了约束范围,但 Composer 没自动降级
怎么确认某个包实际装了什么版本?
composer show -l 是最准的,它只读 composer.lock,不联网、不解析、不猜测:
- 输出里带
[plugin]标记的才是已激活的插件,普通outdated可能漏掉它们 - 对比
composer show vendor/package和composer show -l vendor/package:前者查远程元数据,后者查本地真实状态,两者不一致说明 lock 文件未同步 - 想看源码地址以便查 changelog?用
composer show -s vendor/package拿到source.url,然后手动访问 GitHub Releases 页面
别信 outdated 的输出就动手 update
它只是静态比对,不跑依赖解析,不校验 PHP 版本,也不管扩展是否启用。真正要升级前,必须跑:
-
composer update --dry-run(注意:Composer ≥ 2.2 后该参数已移除,实际应使用composer update --no-install或在干净环境中测试) - 它会暴露
outdated完全看不到的问题:某包升级后,其子依赖冲突、PHP 扩展缺失、甚至整个依赖图无法收敛 - 尤其当
outdated显示laravel/framework: 10.32.0 → 10.40.0,--dry-run却报错说spatie/laravel-ray锁在1.30.0不兼容,这才是真实瓶颈
真正容易被忽略的是:即使 --dry-run 成功,上线前仍得人工核对 major 版本的 UPGRADE.md —— Composer 不会告诉你 Request::ip() 在 Laravel 11 里已被废弃。











