发布于2026-07-14 阅读(0)
扫一扫,手机访问
composer why-not是检测依赖死锁的起点,不是备选方案;它不模拟安装、不修改文件,仅从目标包反向遍历composer.json和composer.lock中的require、conflict及platform约束,精准输出首个不可绕过的硬冲突点,如conflicts行即为真死锁。

先别急着删 composer.lock 或者盲目改版本约束——遇到 root requirements could not be resolved 这种报错时,真正的第一步是跑一下 composer why-not。这玩意儿是唯一一个能立刻告诉你“到底谁在拦路”的只读命令。它不模拟安装、不修改任何文件,只是从目标包出发,反向遍历当前 composer.json 和 composer.lock 里所有的 require、conflict 以及 platform 约束,然后输出第一个根本绕不过去的硬冲突点。
不过有几个常见坑得注意:
composer why-not lara vel/framework:11.0,结果报了个 [InvalidArgumentException] Package not found——八成是版本号没补零,必须写成 lara vel/framework:11.0.0,Composer 对版本号格式很较真。minimum-stability 设置,或者私有仓库能不能访问得到。conflicts 行,比如 conflicts: {"lara vel/framework": ">=11"},这就是真的死锁了,Composer 会直接放弃求解。require-dev 里的某个包间接依赖的,那必须加上 --with-all-dependencies 参数才能穿透检查。假设你打算升级主框架到 Lara vel 11,但还没写进 composer.json 里,这时候 composer why-not 会直接返回空——因为它只检查已经注册的依赖。换个思路,该用 composer prohibits。这个命令不等你“想装什么”,而是主动扫描整个依赖图,把所有明确写着排斥目标版本的包都给列出来。
实操建议:
composer prohibits "lara vel/framework:11.0.0",提前看看 spatie/lara vel-backup 或者 orchestra/testbench 是不是还在锁死旧版。(by your requirements) 的行,那是你自己的 composer.json 在捣乱,不是第三方包的问题。require-dev 里的工具链包——这些包在测试兼容性上往往滞后于主框架。当 composer install 卡住不动、CPU 持续飙升、内存暴涨,大概率不是网络慢,也不是包不存在,而是依赖图里出现了 a → b → a 这种强循环。SAT 求解器在无限回溯,怎么也解不开。
关键操作:
composer show -t --no-dev --ignore-platform-reqs,这样才能逼近真实安装路径。默认行为会包含 require-dev 并跳过平台检查,反而会掩盖真实的冲突。vendor/a/package-a → vendor/b/package-b → 又回到 vendor/a/package-a。| more。所谓的“可配置的 PHP 分布式死锁检测器”,本质上不是写什么新逻辑,而是把 why-not、prohibits、show -t 这三类命令封装成一个统一入口,同时做好参数隔离。比如可以做一个 CLI 工具,接受 --target、--mode=why-not|prohibits|tree、--include-dev 等开关,内部根据模式调用对应命令并过滤输出。
有几个注意事项:
exec() 调用原生命令更可靠,省得自己重实现一遍约束解析。--dry-run -v 在卡住的时候非常关键。它会让日志吐出 SAT 求解器的真实决策痕迹,这不是普通的“日志”,而是求解器的回溯路径。composer self-update --2,否则会提示 Command "why-not" is not defined。why-not 都不负责校验。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8