直接运行 composer why-not 包名:精确版本号可定位冲突源头,如 laravel/sanctum:3.0.0;更推荐 composer prohibits 精确版本号,它从目标包反向追踪真实拦路虎;配合 composer update --dry-run -v 查看 Because 冲突链和 Root requirements 起点,以及 composer show --tree 揭示 require-dev 中隐藏依赖。

报错里 “Conclusion: don’t install xxx” 怎么立刻知道谁在卡住
这不是结果,是求解器放弃前的最后一句提示——它已经算出矛盾点,但没告诉你源头在哪。直接看这行末尾的包名和版本(比如 laravel/sanctum:3.0.0),把它当靶子打。
运行:composer why-not laravel/sanctum:3.0.0
它会输出类似:
myapp/core dev-main requires guzzlehttp/guzzle (^6.5)laravel/sanctum 3.0.0 requires guzzlehttp/guzzle (^7.2)
这两行就锁死了:同一个 guzzlehttp/guzzle,一个要 ^6.5,一个要 ^7.2,范围无交集。注意必须写完整版本号(3.0.0),不能写 ^3.0,否则报 [InvalidArgumentException] Package not found。
composer prohibits 比 why-not 更快定位真实拦路虎
composer why-not 只查你 composer.json 里写了但没装上的包;而 composer prohibits 是从你想装却装不上的那个包出发,反向翻所有直接/间接阻止它的约束。它更接近“真凶画像”。
例如执行 composer require laravel/framework:^11.0 失败,why-not laravel/framework:11.0.0 可能返回空——因为你根本没在 composer.json 里声明过它;但 prohibits laravel/framework:11.0.0 会立刻指出:spatie/laravel-backup v7.2.0 requires symfony/console ^5.4(for spatie/laravel-backup v7.2.0)
括号里的 (for spatie/laravel-backup v7.2.0) 就是真正卡死你的源头。记住:它必须带精确版本号,且只对已发布版本有效。
composer update --dry-run -v 看懂冲突链在哪一行
这个命令不改任何文件,但会把 Composer 的整个依赖求解过程摊开给你看。关键不是开头,是末尾几行:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 盯
Because链:比如Because package-a v2.1 requires monolog/monolog ^1.25, and package-b v3.0 requires monolog/monolog ^2.10—— 这就是无交集的铁证 - 看
Root requirements段落:找出你composer.json里哪条"vendor/name": "^x.y"是整场冲突的起点 - 扫
Found conflicting requirements:列出的具体包名和版本范围,才是你要动手调的对象
不加 -v,你只看到“无法解析”;加了,才能看见“谁在拉扯谁”。别跳过。
composer show --tree 查清谁偷偷引入了冲突包
composer show --tree 输出的是当前 composer.lock 已成功解析的真实依赖结构,不是理想状态,而是现场快照。它能揪出那些“你以为没装、其实早被 require-dev 包拖进来的”冲突源。
常见陷阱:
- 你项目里没直接
require monolog/monolog,但phpunit/phpunit和laravel/sail分别把它拉进来,且版本不一致 → 树里会出现两条路径指向不同monolog版本 -
your-project-name出现在树顶,说明composer.json的require-dev或conflict字段正在参与求解,哪怕你只跑composer install - 某些包通过
replace声明自己是psr/log,但实际行为不兼容,show --tree会暴露这种“假替代”
想快速筛某个包,直接:composer show --tree | grep "symfony/console"
如果某行末尾有 (locked to 5.4.32),说明这个版本已在 composer.lock 固定,不删 lock 或不用 --with-all-dependencies 就没法松动。
最常被忽略的点:冲突往往藏在 require-dev 里,而 composer install 默认也会参与求解。临时验证是否是它拖后腿,可加 --no-dev 再试一次 update --dry-run。不是所有问题都该靠删 vendor 和 composer.lock 解决,那只是重置,不是诊断。










