composer outdated是唯一可信的依赖健康检查命令,它基于composer.lock、Packagist当前稳定版和composer.json约束实时比对,精准报告可更新项;显示可升但update不动主因是依赖冲突,可用--dry-run或--all定位约束源头,--security-only(Composer 2.2+)强制列出含CVE修复的包。

composer outdated 是你唯一该信的依赖健康检查入口,其他命令要么失效、要么是插件、要么压根不存在(比如 composer outpdated)。 它不升级,只告诉你“现在能升什么”,而且这个“能升”是严格基于 composer.lock + Packagist 当前稳定版 + 你 composer.json 中的版本约束三者实时比对出来的结果——不是猜测,不是缓存,不是开发分支快照。
为什么 composer outdated 显示可更新,但 composer update 却不动?
最常见原因是依赖冲突:某个包 A 看似可升到 2.10,但它被另一个已安装包 B 的约束死在 ^2.0,而 B 自己又依赖 C,C 又要求 A ≤2.8 —— Composer 最终选的是满足全图的最高兼容版本,不是单点最大值。
- 运行
composer update --dry-run vendor/package-name查看真实会改哪些包,比outdated更贴近执行结果 - 如果报 conflict,用
composer depends vendor/package-name找出谁在锁它 -
--all参数能暴露那些“被卡住”的包(标为 not upgradable),帮你定位约束源头 - 别迷信
^2.0能升到 3.x;outdated默认只显示满足当前约束的更新,加--all才能看到“其实 3.0 已发,但你的约束拦住了”
composer outdated --security-only 为什么必须用(且只在 Composer 2.2+)
安全更新不是“功能增强”,是“不修就可能被黑”。--security-only 过滤出已确认 CVE 编号、且 Packagist 上已有修复版本的包——它不关心你约束多严,只要存在对应补丁版,就强制列出来。
- 旧版 Composer(composer --version 确认
- 它和
--all不互斥,可以组合:composer outdated --security-only --all,既查漏洞,也看哪些包因约束被拦 - CI 流程中建议固定加此参数,失败时直接阻断构建(例如用
composer outdated --security-only --format=json | jq 'length == 0') - 注意:它只识别 Packagist 官方标记的安全版本,fork 包或私有仓库需自行维护 CVE 映射
怎么避免 dev-main 在 outdated 输出里“消失”或误导?
当你在 composer.json 里写 "monolog/monolog": "dev-main",outdated 默认不会把它当“可更新对象”处理——因为 dev-main 没有语义化版本号,无法比对“最新 stable”。它可能安静地停留在一个早已过期的 commit 上。
- 加
--all强制列出所有包,dev-main行会显示为 dev-main → 2.10.0 或类似,提示你“其实有稳定版了” - 用
--stability=beta或--stability=rc可让outdated把预发布版也纳入比对(适合测试环境) - 生产环境应尽量避免
dev-引用;若必须用,定期跑composer show monolog/monolog看当前 commit hash,并手动比对 GitHub tag -
prefer-stable: true会压制非 stable 版本提示,哪怕你设了minimum-stability: dev,也可能导致outdated忽略某些更新信号
真正难的不是跑对命令,而是读懂输出里每个箭头背后的约束链。一个标黄的 symfony/console 提示可升,背后可能是三个不同子依赖对 PHP 版本、扩展、甚至另一个 Symfony 组件的隐式要求——outdated 告诉你“能升”,但要不要升、怎么升、升完测什么,得你自己顺着依赖图往下摸。


















