答案是运行composer why-not vendor/package:version定位阻塞链,首行包即最上游封杀者;若输出为空则可能版本号错误或minimum-stability限制所致。Composer依赖冲突本质是约束交集为空,SAT求解器已严格证明无解,需聚焦根项目、传递依赖与平台三类约束是否互斥。

Composer 报“依赖死锁”不是真死锁,而是 SAT 求解器穷尽所有组合后确认无解——它已经明确告诉你:当前所有约束(根项目 + 传递依赖 + 平台要求)交集为空。解决的关键不是“重启命令”,而是定位哪条约束卡死了整个链条。
用 composer why-not 直接揪出封杀源头
报错里那句 Conclusion: don't install laravel/framework v10.32.0 是结果,不是原因。真正要查的是“谁在阻止这个版本被选中”。
- 运行
composer why-not vendor/package:version(例如composer why-not monolog/monolog:2.9.0),输出第一行出现的包,就是最上游的硬性封杀者 - 如果输出为空,说明该版本根本没出现在任何
require或conflict字段里——大概率是版本号写错,或该包在当前minimum-stability下不可见 - 别用
composer depends替代,它只显示“谁用了它”,不体现版本限制,容易误判
检查三类约束是否互相打架
冲突永远来自三组条件的交集为空:你自己的 composer.json、下游包的 require 段、以及平台约束(php、ext-* 等)。
-
根项目约束:检查
composer.json里有没有写死过紧的版本,比如"php": "^7.4"却在 PHP 8.0 环境下运行 -
传递依赖约束:两个包分别要求
guzzlehttp/guzzle:^7.0和^8.0,没有交集就必然失败 -
平台约束:某个包声明
"php": ">=8.1",而你本地是 8.0 —— 这类“约束比事实保守”的情况在 PHP 升级时特别常见
别碰 composer.lock 文件本身
手动编辑 composer.lock 极其危险。它不是配置文件,而是依赖图的哈希快照。改错一个 version 或 dist/sha256 字段,下次 composer install 就会直接失败。
- Git 合并导致
composer.lock冲突?删掉冲突标记后的整个文件,再跑composer update --lock重生成 - 想保留某分支的依赖结构?先
git checkout那个分支,再执行composer update vendor/package重装另一分支引入的包 - 永远不要在合并后直接
composer install—— lock 文件已损坏,install 必然失败
最常被忽略的一点:require-dev 包全程参与解析。从 Composer 1.7 开始,哪怕你加了 --no-dev,dev 包的约束也会影响主依赖树构建。很多隐藏冲突就藏在这里。


















