
Composer 遇到循环依赖不会绕过、不降级、不忽略,它直接中止解析并报错——这不是配置问题,而是依赖图在逻辑上不可解。
怎么一眼识别是不是循环依赖
看到这些错误,基本可以锁死是循环依赖:
Root package cannot be installedPackage a depends on b, which depends on a-
Your requirements could not be resolved to an installable set of packages(配合 CPU 持续飙升、终端卡住几十秒才退出)
注意:composer validate完全没用,它只校验 JSON 格式;composer show默认带 require-dev,会掩盖真实生产依赖路径;真正有效的线索藏在 --dry-run -v 输出末尾反复出现的包名,或 composer depends --tree 中出现的自指路径(如 myorg/core ← myorg/api ← myorg/core)。
用 composer depends --tree 定位闭环链
这个命令是目前最准的诊断入口,但必须满足两个前提:项目已成功 composer install 过(保证 composer.lock 有完整依赖快照),且加 --tree 参数。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 查可疑包:运行
composer depends myorg/core --tree,看输出里是否出现myorg/core被自己间接依赖两次 - 如果报
Package not found,说明该包根本没进composer.lock,大概率被解析阶段提前拦截了,先执行composer clear-cache再试 - 别只查一级依赖:
composer depends myorg/core(无--tree)只会显示直接上游,漏掉A → C → B → A这类间接环
最容易被忽略的隐式循环:autoload + require-dev
不是你手动写了 "myorg/api": "dev-main",而是某个 require-dev 包(比如 phpunit/phpunit 或某个自定义测试工具)在自己的 composer.json 里声明了:"autoload": {"psr-4": {"App\": "../src/"}}——它把你的 src/ 加进了自己的自动加载路径,而你的代码又用了它的类,形成运行时闭环。
- 检查所有
require-dev包的composer.json,重点搜../、../../、src/、tests/这类路径 - 临时注释掉非必要
require-dev条目,尤其是喜欢跨项目 autoload 的工具(infection/infection、phpstan/phpstan插件等) - 确认你自己的
autoload-dev没把vendor/下的路径写进去——这等于告诉 Composer:“我依赖我自己”
破环只有三种靠谱方式,没有“跳过”选项
所有临时手段(删 composer.lock、加 --ignore-platform-reqs、改 minimum-stability)都只是掩盖症状。真正解法只有重构依赖方向:
- 抽离契约包:新建
myorg/contracts,里面只放接口、DTO、异常,"require": {}为空;core和api都只require "myorg/contracts": "^1.0" - 运行时解耦:A 不再
new B()或use BClass,而是定义LoggerInterface(放契约包),B 实现它,A 通过容器获取;同时 A 的composer.json必须删掉对 B 的require - 降级为可选:B 只在 A 的测试中用?移到
require-dev;是增强功能(如导出 Excel)?改用suggest字段提示用户手动安装
复杂点在于:很多循环不是显式 require,而是通过 replace、provide、path 仓库或分支别名(如 "dev-main as 1.0.x-dev")悄悄形成的。一旦怀疑,就用 composer show -t --no-dev --ignore-platform-reqs 模拟真实安装路径,人工扫树里重复出现的包名组合。










