composer依赖冲突本质是约束无交集,需先用composer why-not定位阻断源,再通过composer show和--dry-run验证实际安装版本与拟变更影响,警惕conflict字段和lock文件不一致。

Composer依赖冲突不是“装不上”,而是它明确告诉你:没有一组版本能同时满足所有约束——诊断的核心,就是找出哪条约束在卡住你。
用 composer why-not 直接问谁在拦路
报错里只写 Conclusion: don't install laravel/sanctum:^3.0?别猜。运行:
composer why-not laravel/sanctum:^3.0
它会输出真实阻断链,比如:
myapp/myproject dev-main requires guzzlehttp/guzzle (^6.5)laravel/sanctum ^3.0 requires guzzlehttp/guzzle (^7.2)
这就锁定了冲突源头是 guzzlehttp/guzzle 的版本范围无交集。注意:why-not 查的是“你想装但装不了”的包;如果还没装成功,composer why 查不到有效路径。
查当前实际装了什么:composer show 和 composer show --tree
别只看 composer.json 里写的约束,重点看 lock 文件里最终落定的版本:
-
composer show guzzlehttp/guzzle—— 显示已安装版本、它的require列表、支持的 PHP 版本 -
composer show --tree—— 展开完整依赖树,一眼看出哪个包把guzzlehttp/guzzle拉成了^6.5
常见陷阱:自己项目 composer.json 没写死 guzzle,但某个 SDK 或 require-dev 里的 phpunit/phpunit 间接锁死了它。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
别跳过 --dry-run,先看它想动什么
执行 composer update vendor/package --dry-run 或 composer require new/package --dry-run,它不改任何文件,只输出拟变更清单:
- 哪些包会被升级/降级(尤其注意主版本号变化,比如
v2→v3) - 是否触发意外的传递依赖更新(比如升
guzzle连带把symfony/http-foundation从v5推到v6) - 有没有报新的
conflict提示(说明你刚解了一个,又撞上另一个)
全量 composer update 容易让 SAT 求解器卡住几分钟,还可能引入新问题;--dry-run 是可控性的第一道防线。
警惕 conflict 字段和 composer.lock 不一致
有些包在自己的 composer.json 里写了 "conflict": {"laravel/framework": ">=11.0"},哪怕你项目没装 L11,只要其他依赖把它间接拉进来,Composer 就会全局拒绝——conflict 是硬性拦截,不是提示。
另外,composer install 报 conflict,往往是因为 composer.lock 和当前 composer.json 不匹配:
- Git 拉了别人提交的新
require,但没同步lock文件 - 手动改了
composer.json后忘了跑composer update --lock
此时先 composer install --dry-run,再对比两份文件里同名包的版本字段,比直接删 vendor/ 更快定位真问题。
真正难的不是命令怎么打,而是读懂 why-not 输出里那几行字背后的真实依赖链——它常藏在 require-dev、私有 SDK 或早已弃用的旧包里,而不是你正盯着的那个报错包。










