必须用 composer outdated --all、composer update --dry-run、composer audit 三步交叉验证升级,否则易在 ci 或上线后触发 call to undefined method 或 argumentcounterror。

直接结论:别信“升了再说”,升级前必须用 composer outdated --all + composer update --dry-run + composer audit 三步交叉验证,否则大概率在 CI 或上线后爆 Call to undefined method 或 ArgumentCountError。
怎么看哪些包真该升、哪些只是“看起来能升”
很多人跑完 composer outdated 看到一堆黄色箭头就动手 update,结果发现有些包根本没在项目里被调用,纯属传递依赖;有些则锁死在旧版是因为上游有冲突,硬升会触发 Your requirements could not be resolved。
-
composer outdated默认只扫require里显式声明的包,require-dev和间接依赖(比如psr/log)全不出现 —— 想看全貌,必须加--all - 输出里带
!的行(如guzzlehttp/guzzle 7.4.5 → 7.5.0 !)不是装饰,是 Composer 从其conflicts字段识别出 BC-breaking 更改,必须查 CHANGELOG - 标着
not in require的包,说明没人直接声明它,得先跑composer depends vendor/package-name确认谁在用它,再决定是否动 - 如果
outdated输出为空,别以为万事大吉 —— 可能是composer.lock没提交、本地缓存过期,或包已弃用但没发新 tag
怎么预判升级会不会炸掉测试套件
真正危险的不是版本号跳变,而是接口签名变更、类被删、方法参数加了 nullable 类型 —— 这些不会被 outdated 提醒,但会在 PHPUnit 运行时直接报错。关键不是“能不能升”,而是“升完代码还跑不跑得通”。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 执行
composer update --dry-run,它会模拟整个依赖解析,告诉你实际会更新哪些包、是否降级、有没有冲突,比outdated更接近真实影响 - 对比
composer.lock变更行数:理想情况 ≤ 5 行;若上百行,说明波及面过大,暂停,改用--with-dependencies小步推进(例如只升guzzlehttp/guzzle --with-dependencies) - 测试失败堆栈里一旦出现
Call to undefined method或ArgumentCountError,基本可锁定是某个依赖改了契约 —— 此时不要翻 changelog,先用composer show -a vendor/package-name查它所有已发布版本的requires和conflicts,快速定位冲突源头 - 别跳过
APP_ENV=testing和bootstrap路径检查:Laravel 项目里若phpunit.xml的bootstrap指向错路径,测试根本没加载新类,失败原因会被误判为“依赖问题”
安全漏洞不能靠 outdated 发现,audit 也得会读
composer outdated 完全不查 CVE,哪怕 monolog/monolog 刚爆 RCE,只要没发新版,它就显示“无更新”。而 composer audit 是唯一官方途径,但它有硬限制。
- 必须用 Composer ≥ 2.5,低于此版本运行
composer audit会报Command "audit" is not defined;升级命令是composer self-update -
audit只检测vendor/中**已安装**的包,且默认只对接 Symfony Security Advisory Database,不覆盖 NVD/CVE 全库 - 输出里
severity: critical不等于 CVSS ≥ 9.0,只是 Symfony 团队的主观分级;solution字段常写 “Upgrade to X.Y.Z”,但没说要不要改代码适配 —— 得自己点开link看原始通告 - 私有包、fork 包、
path仓库默认被跳过,audit结果为空不等于安全,只是没被扫描到
lock 文件不是缓存,是契约,删了重生成就是放弃控制权
很多团队把 composer.lock 当成可删文件,CI 里直接 composer install 失败就 rm composer.lock && composer install —— 这等于主动放弃对依赖一致性的控制,CI 和本地环境行为可能完全不同。
-
composer.lock里存的是每个包的 exact commit hash、PHP 扩展要求、甚至平台配置(如ext-curl是否启用),不是简单版本号 - 没有
lock文件时,composer install实际会走一遍update流程,解析整张依赖图、请求 Packagist 元数据 —— CI 时间多出 2–5 分钟是常态 - 团队协作中,
composer.lock必须提交,且每次update后要人工确认变更是否合理;看到symfony/console从 v6.3 升到 v7.0,就得立刻停手,查文档是否需 PHP 8.2+ - 用
composer show -l交叉验证:它输出vendor/composer/installed.json里的真实安装状态,和outdated结论冲突时,优先信show -l—— 很可能是lock文件被手动改过或没提交
最常被忽略的一点:升级风险不在命令本身,而在你没看清 composer show -a 输出里的 type 字段。如果是 symfony-bundle,它强耦合框架生命周期,升了却没同步调整 config/bundles.php,服务容器直接报错 —— 这种问题 --dry-run 也拦不住,得靠人眼扫。










