Composer 不自动解决版本冲突,仅在约束有解时推导唯一组合;冲突时需用 composer why-not 定位阻断链,优先检查 require-dev,升级必须加 --with-dependencies 并验证 lock 文件。

Composer 从不自动解决版本冲突——它只在约束有解时推导出唯一组合;一旦多个包对同一依赖提出互斥要求(比如 guzzlehttp/guzzle 要求 ^6.5 和 ^7.2),它就穷举失败并报错,不会降级、跳过或妥协。
用 composer why-not 定位谁在封杀目标版本
报错里写的 don't install monolog/monolog:3.0.0 是结论,不是原因。必须立刻运行:
-
composer why-not monolog/monolog:3.0.0—— 输出会逐层列出阻断链:A 包 require B 包,B 包 require C 包,C 包锁死monolog在2.9.1 - 第一行常是你的根项目(如
myapp/myproject dev-main)在require或require-dev中硬写了旧版 - 如果输出为空或只显示
nothing,说明该版本根本不在 Packagist 上,不是冲突,是版本不存在 - 特别注意
require-dev里的包,比如phpunit/phpunit或私有 SDK,它们常悄悄拉入不兼容的子依赖
别删 composer.lock,先用 composer update --lock 验证一致性
删 lock 文件等于丢掉现场线索,还可能让 Composer 在本地重算出 CI 或生产环境无法复现的组合。更安全的做法是:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
composer update --lock—— 它不改vendor/,只按当前composer.json重生成合法composer.lock,失败时直接暴露真实约束矛盾 - 如果失败,说明
composer.json里存在隐式冲突(例如同时 require 两个互斥框架),此时再跑composer why-not - 成功后立刻
git diff composer.lock,确认只有预期变更;多改一个symfony/polyfill-*都可能埋下运行时隐患
定点升级必须带 --with-dependencies,否则大概率失败
想升 monolog/monolog 到 3.0.0,只跑 composer update monolog/monolog 常被拒绝——因为 monolog 3.0 可能要求 php >=8.1 或 psr/log ^3.0,而这些旧版本还卡在 composer.lock 里。
- 必须加
--with-dependencies:composer update monolog/monolog --with-dependencies - 不能写
composer update "monolog/monolog:^3"—— 引号 +^会让 Composer 自行找最新兼容版,不是你要的精确版本 - 如果仍失败,查
composer show monolog/monolog的require列表,把关键子依赖(如psr/log)一并列进命令:composer update monolog/monolog psr/log --with-dependencies - 升级后立刻
git diff composer.lock,确认改动范围可控
真正容易被忽略的是:冲突往往藏在 require-dev 里,而 composer why-not 的输出第一眼看不到它;还有就是 --with-dependencies 不是可选项,是必须项——没有它,Composer 就当那个包是“孤立升级”,根本不考虑它的依赖门槛。

















