composer update卡在resolving dependencies且cpu跑满即为循环依赖,非版本冲突;需用composer update --dry-run -v查末尾闭环路径,再以composer depends --tree实锤链路,破环须抽离契约包、拆分单体包或运行时解耦。

composer update卡在Resolving dependencies且CPU跑满,就是循环依赖
这不是版本冲突,是依赖图里存在 A→B→A 这类闭环,Composer 的 SAT 求解器会在里面无限回溯。现象是终端卡住、CPU 持续 95%+、内存暴涨后突然退出,而不是报具体错误。
先运行 composer update --dry-run -v,盯最后几行输出:如果反复出现同一组包路径(如 vendor/a → vendor/b → vendor/a),或某个包名连续出现 ≥3 次且父级不同,基本可确认闭环。
- 必须加
-v和--dry-run,不改文件但走完整解析流程 - 别只看开头报错,关键信息全在末尾“求解器临终遗言”里
- 如果
composer depends --tree报Package not found,说明锁文件已损坏,先删composer.lock和vendor/再试
用composer depends --tree实锤闭环链路
composer depends --tree 是唯一能看清间接环的命令,但它有两个硬前提:项目得有有效的 composer.lock,且必须带 --tree 参数。否则只显示一级依赖,完全漏掉 A→C→B→A 这种多跳环。
运行 composer depends myorg/core --tree,如果输出含 myorg/core ← myorg/api ← myorg/core(箭头方向是“被谁依赖”),自身出现两次即闭环成立。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 临时注释掉
composer.json中所有require-dev条目再试,很多环藏在phpunit/phpunit或phpstan/phpstan的 autoload 里 - 重点检查这些 dev 包的
autoload是否含../、../../、src/—— 它们会把你的代码反向拉进加载路径 - 你自己的
autoload-dev里如果写了vendor/下的路径,等于告诉 Composer:“我依赖我自己”
破环只有三种有效方式,没有--force或--skip-cycle
Composer 不提供“忽略循环”的开关。所谓“降级”“跳过校验”全是临时止痛,问题仍在。真正解法只有结构层面干预:
- 抽离契约包:把双方共用的接口、DTO、异常拎出来,建新包
myorg/contracts,然后myorg/core和myorg/api都只require "myorg/contracts": "^1.0" - 拆分单体包:把打包在一起的
myorg/core按职责切成myorg/core-api和myorg/core-domain,让 api 层依赖 domain,但 domain 不反向依赖 - 运行时解耦:把硬依赖改成接口 + Service Locator / Container::get() + 条件判断,避免 autoload 在加载阶段就打通双向路径
为什么删 composer.lock + composer install 不解决问题
删了 composer.lock 后跑 composer install 会直接报错:Lock file does not exist。因为 install 的设计目标是“精确还原”,它只认锁文件,根本不读 composer.json 的版本约束。
真正触发重算依赖图的是 composer update——它会读 composer.json、调用 SAT 求解器、生成新 composer.lock。但如果你没先破环,update 会立刻回到原点:卡在 Resolving dependencies。
- 别指望
--ignore-platform-reqs或--no-cache能绕过循环,它们只影响平台校验和缓存读取 - 手动改
composer.lock更危险:hash 校验失败会导致install直接拒绝加载 - 最常被忽略的破环入口是
require-dev和autoload的交叉引用,不是require字段本身










