必须用composer outdated --all、composer update --dry-run、composer audit三步交叉验证,否则易在ci或上线后触发call to undefined method或argumentcounterror;outdated仅报版本号不报接口变更,audit才查cve,--dry-run不暴露autoload问题。

别指望 composer outdated 能告诉你有没有风险——它只报版本号,不报接口删了、参数变了、类名改了。真要识别依赖风险,必须把 composer outdated --all、composer update --dry-run、composer audit 三步串起来跑,缺一不可。
为什么 composer outdated 单独用等于没看
它默认只扫 require 里明写的包,require-dev 和间接依赖(比如 psr/log)全不出现;输出带 ! 的行(如 guzzlehttp/guzzle 7.4.5 → 7.5.0 !)不是装饰,是 Composer 从 conflicts 字段推断出有 BC-breaking,但具体哪块破了,它不说。
- 没在
require里声明却出现在outdated --all输出里的包,得先跑composer depends vendor/package-name确认谁在拉它,再决定动不动 -
outdated输出为空,不代表安全:可能是composer.lock没提交、本地缓存过期,或包已弃用但没发新 tag - 它完全不查 CVE ——
monolog/monolog刚爆 RCE,只要没发新版,它就显示“无更新”
composer audit 怎么用才不漏报
它只比对 composer.lock 里记录的**精确版本哈希**和 Symfony 安全数据库(FriendsOfPHP/security-advisories),不是扫 vendor/ 目录,也不是读 composer.json 的模糊约束。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 必须先运行
composer install或composer update,否则vendor/为空或哈希不匹配,audit结果就是 “No vulnerabilities found” - 私有包、fork 包、
path类型仓库默认跳过,除非你在composer.json里显式配了"type": "package"并提供安全元数据 - CI 中别用默认行为卡点:加
--level=high --level=critical --no-dev,避免 low 级别旧漏洞拖垮流水线
composer update --dry-run 的关键陷阱
它能列出所有将被更新的包,但不执行 autoload-dump,所以自动加载冲突、类找不到这类问题它根本暴露不了。
- 一定要加
--with-dependencies,否则像symfony/http-kernel升级会连带更新psr/cache,但--dry-run不加这个参数就看不到 - 如果项目用了
config.platform(比如锁定"php": "8.0"),得人工核对--dry-run结果里有没有包要求php:^8.2这种越界版本 - 想测多个包组合?用
composer update vendor/a vendor/b --dry-run,别直接composer update全量刷,干扰太大
真正危险的变更,outdated 和 audit 都不提醒
比如方法签名加了 nullable 类型、返回类型从 array 改成 list、构造函数参数顺序调整、事件监听器接口方法被删——这些不会触发 outdated 标 !,也不会进 audit 数据库,但 PHPUnit 一跑就崩。
- 升级后优先跑
vendor/bin/phpstan analyse src/,类型变更它立刻报错 - 用
grep -r "new HttpKernel" tests/找显式实例化的地方,这些最易因构造函数变化而挂 - 检查
composer.lock差异时,重点盯psr/、symfony/、league/这类底层包的子依赖变动,它们一动,上层大概率静默失效
风险不在版本号跳了几位,而在你代码里调用它的那几行是否还合法。每次升级前,这三步少一步,上线后 Call to undefined method 就在等你。










