composer why-not 只分析已安装或锁定的依赖冲突,不解决网络、权限、PHP版本等外部问题;需指定失败包名和版本,输出中带conflicts的行及最终指向的已安装包是关键卡点。

composer why-not 能直接告诉你某个包为什么装不上,但它不是万能的——它只分析已安装或已锁定的依赖冲突,不解决网络、权限、PHP 版本不兼容等外部问题。
why-not 命令的基本用法和触发时机
当你执行 composer require vendor/package 失败,并看到类似 Conclusion: don't install vendor/package v1.2.3 的结论时,why-not 就该上场了。它需要你明确指定「想装但失败」的包名和版本(或约束)。
- 最常用形式:
composer why-not vendor/package:^2.0 - 如果没写版本,默认按
composer require时尝试解析的版本来查,但建议显式带上,避免歧义 - 它不支持通配符或模糊匹配,
vendor/*或package@dev这类写法会报错
常见输出解读:哪些行才是真正卡点
命令输出是一段逻辑链,从目标包开始倒推,每行以 requires 或 conflicts 连接。关键要盯住带 conflicts 的那几行,以及最终指向的已安装包(如 monolog/monolog 或 php)。
-
php ^8.0conflicts withyour-project→ 说明项目composer.json中"php"约束太低(比如"^7.4"),升不上去 -
symfony/consolev5.4 conflicts withlaravel/frameworkv9.0 → 框架锁死了依赖范围,不能硬塞高版本 -
vendor/packagerequiresext-redis-> 但系统没启用该扩展,why-not不会提示这个,它只管 Composer 级依赖图
它查不到的三类典型原因
why-not 完全不涉及运行环境和配置层,以下问题需另查:
-
Could not fetch https://repo.packagist.org/p2/vendor/package.json→ 网络不通或 Packagist 访问受限,和依赖冲突无关 -
Package container-interop/container-interop is abandoned→ 是弃用警告,不是安装失败原因;why-not不显示弃用信息 -
require-dev里写了包,但你在--no-dev模式下 install →why-not仍会查整个依赖图,但实际失败可能只是因为 dev-only 包被跳过
composer why-not guzzlehttp/guzzle:^8.0 # 输出示例节选: guzzlehttp/guzzle 8.0.0 requires php ^7.2.5 || ^8.0 -> your project requires php ^7.1.3. So, guzzlehttp/guzzle 8.0.0 is not satisfiable.
真正卡住的永远是最后一句:它把冲突归结到你的 composer.json 中 "php" 字段。改这里,比反复换 guzzle 版本更治本。










