composer install 卡在“resolving dependencies”是因本地 sat 求解器穷举版本组合,与镜像无关;根本原因是隐式循环依赖、宽松约束+私有包导致搜索爆炸、或本地缓存损坏,需通过 clear-cache、精简约束、规范 platform 配置来优化。

composer install 为什么卡在 “Resolving dependencies” 而不是下载慢
这不是镜像源没生效,而是 Composer 在本地做 SAT 求解——它正在穷举满足 composer.json 所有 require 版本约束的组合,跟镜像无关。Metadata(元数据)解析阶段完全离线,只读 composer.lock 和本地缓存的 packages.json,不发任何网络请求。
常见诱因:
- 多个包之间存在隐式循环依赖(如
arequireb:^2.0,brequirea:^1.5),求解器陷入回溯爆炸 -
composer.json中混用宽松版本约束(^、~)和大量私有包,搜索空间指数级增长 - 本地缓存损坏:缓存中某个
packages.json文件被截断或 JSON 格式错误,导致解析器反复重试
验证方式:加 -vvv 运行 composer install,若日志停在 Reading /root/.composer/cache/repo/https---repo.huaweicloud.com-repository-php/packages.json 之后、无 HTTP 请求日志,就是纯本地求解卡住。
metadata 增量 diff 真正起作用的场景只有 update,不是 install
composer install 不生成新 metadata,它只校验 composer.lock 与 vendor 是否一致;只有 composer update 才会触发 metadata diff —— 但这个 diff 不是“比对两个 lock 文件”,而是 Composer 内部用增量方式复用已解析的依赖图节点,跳过未变更子树的重新计算。
关键限制:
- diff 仅在
composer.lock存在且格式兼容时启用;删掉 lock 或降级 Composer 版本会导致全量重算 - 只要
composer.json的require或require-dev有任意一行变动(哪怕只是空格),整个依赖图顶层节点就被标记为 dirty,增量失效 - 私有仓库 URL 变更、
repositories数组顺序调整,都会让缓存的 metadata hash 失效
所以别指望靠“小改一行版本号”就能秒级 update —— 实际中 90% 的所谓“增量”都被这些隐式变更打断。
想提速 metadata 解析?优先清理缓存而非换镜像
镜像源只加速下载,不影响 metadata 解析速度。真正拖慢解析的是本地缓存中堆积的陈旧、碎片化 packages.json 文件。Composer 2.9.6 默认不会自动清理它们。
实操建议:
- 定期运行
composer clear-cache,尤其在切换 major 版本后(如从 PHP 8.2 升到 8.3) - 禁用不必要的平台配置:如果项目不依赖
ext-gd,就别在composer.json里写"platform": {"ext-gd": "1"},否则求解器会多出一个维度约束 - 把
minimum-stability显式设为"stable",避免求解器尝试匹配dev-master等不稳定分支 - 检查
vendor/composer/installed.json是否异常庞大(>5MB)——那是 metadata 缓存污染的信号,此时clear-cache比调参数更有效
--ignore-platform-reqs 不是万能钥匙,可能让 diff 更慢
加 --ignore-platform-reqs 会让 Composer 跳过 PHP 版本、扩展等平台约束检查,看似能绕过求解瓶颈。但它实际效果是:关闭所有平台相关剪枝逻辑,导致搜索空间反而扩大,metadata diff 的复用率下降。
典型副作用:
- 原本可快速排除的 PHP 8.4-only 包,现在要等到下载后才发现不兼容,白跑一轮解析
- 求解器无法利用
ext-opcache存在这一事实提前剪枝,必须穷举所有不含 opcache 的组合路径 - CI 环境中若用不同 PHP 版本构建,
--ignore-platform-reqs会导致每次生成的 dependency graph 完全不同,彻底废掉增量缓存
正确做法:在 composer.json 的 config.platform 里声明目标环境真实能力,比如 {"php": "8.3", "ext-opcache": "8.3"},既保证一致性,又保留剪枝能力。
metadata 解析没有“算法开关”可调,它的效率取决于你给 Composer 的约束是否干净、缓存是否健康、以及 lock 文件是否真正被尊重——而不是镜像地址末尾有没有斜杠。











