答案是composer why-not vendor/package:version可逆向追踪阻塞链,首行“root package requires”暴露手动约束过窄,必须用完整版本号(如monolog/monolog:2.9.0),不可用^或~;输出为空说明未声明该包或已被conflict屏蔽。

composer why-not 能直接定位阻塞源头
遇到 Conclusion: don't install vendor/package:version 这类报错时,别急着改 composer.json 或硬加 --ignore-platform-reqs。Composer 自带的 composer why-not 是唯一能逆向追踪“谁锁死了这个版本”的命令。
它从你要装的包出发,一层层往上查:哪个包要求了更窄的版本?哪个中间依赖又把它进一步收紧?输出里第一行通常是 Root package requires,也就是你手动写的约束太死(比如 "php": "7.4" 或 "monolog/monolog": "1.25.0")。
- 必须带具体版本号:例如
composer why-not monolog/monolog:2.9.0,不写版本会报错 - 输出中每行都含版本约束,重点关注带
requires和conflicts的行 - 如果某行显示
spatie/laravel-backup 6.10.0 requires monolog/monolog ^1.25,那就说明不是 Laravel 本身卡住,而是这个备份包还没适配 Monolog 2.x
composer show -t 显示完整依赖树结构
当你怀疑某个包被间接拉入、但不确定是谁引入的,composer show -t 比 composer show 更有用。它把整个依赖层级展开,缩进表示嵌套关系,一眼就能看出 package-A 是通过 package-B → package-C 这条链被带进来的。
注意:composer show -t 默认只显示已安装的包。如果某个包根本没装上(因为冲突),它不会出现在树里——这时候得先用 why-not 定位阻塞点,再补全树。
- 加
--direct可过滤出仅直接 require 的包:composer show -t --direct - 加
vendor/package可聚焦查看某包的子依赖:composer show -t monolog/monolog - 输出中若出现
[dev-main]或[no version],说明该包是 VCS 源或未打 tag,容易引发解析歧义
composer depends 不适合查冲突,但适合验证移除影响
composer depends 的作用是“谁依赖我”,不是“谁阻止我”。它列出所有显式声明依赖该包的项目或库,但不体现版本约束细节。所以它无法回答“为什么不能装 2.9.0”,只能回答“如果我把 monolog 升到 2.9.0,哪些包会跟着动?”
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
它真正的用途是:在你准备删掉或替换某个包前,快速确认影响范围。比如你想弃用 guzzlehttp/guzzle 改用 symfony/http-client,先跑一遍 composer depends guzzlehttp/guzzle,看有没有核心业务逻辑直依赖它。
- 输出为空表示没有包显式 require 它(可能是自动加载或运行时反射调用,需代码审计)
- 如果输出里有
laravel/framework,说明框架本身强依赖,不能随便删 - 不要用它替代
why-not,二者解决的是完全不同的问题
锁文件合并冲突时,别手动改 composer.lock
Git 合并分支后,composer.lock 出现 install 很可能报 lock file is not up to date 或直接失败。
正确做法是放弃当前 lock 文件,让 Composer 重算:
- 先确保
composer.json已合并干净(无冲突标记) - 运行
composer update --lock,它会按当前composer.json重新生成完整 lock 文件 - 如果只想保留部分旧版本,用
composer update --with=vendor/package:^x.y限定范围 - 执行后立刻
git diff composer.lock,确认只有预期变更;多出几十个包就说明约束没控住,得回退
真正难处理的从来不是命令怎么输,而是看到 why-not 输出里第三层依赖来自一个两年没维护的私有包,或者 show -t 里某个包的版本号写着 dev-develop —— 那时候你得决定,是修它,还是绕开它。










