php 8.1+ 原生支持 fiber 但无版本号,导致 composer 因包声明 "ext-fiber": "^1.0" 而报错;应通过 composer.json 的 "platform" 或 "replace" 字段欺骗解析,升级相关库或设置 amp_fiber=0 解决运行时问题。

Composer 安装时提示 ext-fiber 不可用或版本不匹配
PHP 8.1+ 原生支持 Fiber,但很多协程库(如 amphp/amp、swoole/ide-helper 或旧版 react/promise)在 composer.json 中仍硬性声明 "ext-fiber": "^1.0" 或依赖已废弃的 symfony/flex 插件逻辑。Composer 会直接拒绝安装,报错类似:Your requirements could not be resolved to an installable set of packages.
根本原因不是 PHP 缺少 Fiber,而是包的 require 字段写死了扩展版本号,而原生 ext-fiber 在 PHP 中没有版本号(`php -m | grep fiber` 只显示模块名),Composer 默认认为它版本是 0.0.0。
- 临时绕过:运行
composer install --ignore-platform-reqs—— 仅限开发验证,上线前必须修复 - 正确做法:在项目根目录
composer.json的platform段显式“欺骗”Composer:"platform": { "ext-fiber": "1.0.0" }注意:这个值只是占位符,只要非空且能被语义化版本解析即可,不需要真实存在 - 若用 Composer 2.5+,还可加
"platform-check": false防止自动检测干扰
amphp/amp v3 升级后 Amp\Future::await() 报 Fiber is not available
这不是 Composer 问题,而是运行时检测失败。Amp v3 默认启用 Fiber 支持,但它调用 extension_loaded('fiber') 后,还会检查 function_exists('Fiber::suspend') —— 这在 PHP 8.1.0~8.1.2 存在 bug(部分构建未导出该方法)。即使 ext-fiber 已加载,也会误判。
- 确认 PHP 版本:运行
php -v,若低于8.1.3,升级 PHP 是最稳妥解法 - 不升级时,强制禁用 Fiber 回退到 Generator 模式:设置环境变量
AMP_FIBER=0(CLI 下启动前加,Web 服务器需在配置中透传) - 不要改 Amp 源码或 patch
Future.php,下个 minor 版可能移除该检测逻辑
使用 swoole/ide-helper 导致 composer update 失败
该包在 v4.8.x 之前把 ext-fiber 写进了 require-dev,且未设 conflict 排除 PHP 8.1+ 原生 Fiber 场景,导致 Composer 认为「你既装了原生 Fiber,又需要一个叫 ext-fiber 的第三方扩展」,产生逻辑冲突。
立即学习“PHP免费学习笔记(深入)”;
- 升级到
swoole/ide-helper:^4.9或更高 —— 它已移除对ext-fiber的 require 声明 - 若必须锁旧版,手动在项目
composer.json加"replace": {"ext-fiber": "*"},向 Composer 表明「我自带 Fiber,不需要你管」 - 注意:此
replace仅影响依赖解析,不解决运行时兼容问题
为什么 ext-swoole 和原生 Fiber 能共存却仍报错?
Swoole 5.0+ 默认启用 Fiber 支持,但它内部做了双模式适配:有 ext-fiber 就用原生,没有就 fallback 到自己的协程调度器。但它的 composer.json 仍声明 "ext-fiber": "*",只为满足旧版 Composer 的平台检查逻辑,和实际运行无关。
- 错误通常来自其他包(比如某个测试工具依赖了过时的
phpunit/phpunit,它又间接拉入了 Fiber 检测库) - 排查命令:
composer why ext-fiber找出谁在 require 它;再用composer depends amphp/amp看哪些包依赖 Amp - 别盲目删
vendor重装——先composer show --tree看依赖树,定位真正作梗的包
协程库的 Fiber 适配不是非黑即白的开关,而是多层检测叠加的结果:Composer 解析阶段、autoload 加载阶段、运行时函数存在性检查、以及 Swoole/Amp 自身的运行时策略选择。漏掉任意一层,都可能在不同环节突然报错。











