composer不提供独立冲突检测命令,真正有效的是用composer update --dry-run -v完整暴露因果链,配合composer why-not、composer show --tree和composer diagnose/validate精准定位根源。

Composer 不提供“检测冲突”的独立命令,所有冲突检测都发生在执行解析类命令时;真正有用的不是“检测”,而是让 Composer 把拒绝理由完整摊开给你看。
用 composer update --dry-run -v 暴露全部因果链
这是最接近“冲突检测”的实操动作。它不改任何文件,但会完整走一遍依赖求解流程,并逐层打印拒绝原因。
- 必须加
-v(verbose),否则嵌套的because行会被折叠,你只能看到最终失败,看不到“为什么” - 输出中每行以
-开头,重点盯住含because的缩进行,它们构成因果链,例如:- monolog/monolog 2.10.0 requires php ^7.2 || ^8.0 -> your PHP version (8.1.0) does not satisfy that requirement. - 如果某个包在多条路径下都被拒绝,说明它被多个约束交叉卡死,需逐条比对约束条件和当前环境
用 composer why-not 定位升级阻塞点
当你想升某个包却失败时,composer why-not 是唯一能逆向查到“谁在拦路”的命令。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 必须带完整版本号,例如
composer why-not laravel/framework:11.0.0,只写laravel/framework会返回空 - 输出从下往上读:最上面一行通常是
Root package requires,说明是你composer.json里写了过窄的约束(比如"php": "8.2") - 如果输出为空,优先检查
require-dev—— 很多阻塞来自phpunit/phpunit或mockery/mockery拉着老版sebastian/exporter
用 composer show --tree 看真实安装快照
composer.json 是愿望清单,composer show --tree 才是 vendor 里实际长出来的依赖树。它读的是 composer.lock 和 vendor/,不是推测结果。
- 不加参数会输出全量树,信息爆炸;务必配合
grep过滤,例如:composer show --tree | grep "guzzlehttp/guzzle" - 看到某行末尾标着
(locked to 7.8.1)或(replaced),说明这个版本已被固定或替代,靠改上层约束绕不过去 - 若发现同一包被两个不同路径引入(如一次来自
laravel/framework,一次来自spatie/laravel-backup),基本坐实间接冲突
别跳过 composer diagnose 和 composer validate
很多“冲突”其实源于基础配置错误或锁文件损坏,这两步必须前置执行,否则你在调试一个根本没加载成功的环境。
-
composer diagnose检查 PHP 版本、扩展、缓存、网络连通性等平台层前提,例如提示PHP version is too old或cache directory is not writable -
composer validate验证composer.json格式是否合法,同时检查composer.lock是否缺失已声明的包,例如报错:Required package "guzzlehttp/guzzle" is not present in the lock file. - 如果
composer validate报错说lock file has some errors,先运行composer update --lock再继续分析
真正难处理的从来不是报错本身,而是 --dry-run -v 输出里反复出现的包名——它大概率是整个依赖图的枢纽,而你可能连它在哪声明的都不知道。










