composer check-platform-reqs 报 ext-ffi 缺失而 php -m 显示存在,本质是 CLI 加载了错误 PHP 二进制或配置,需用 php --ini 确认实际加载的 php.ini 路径,并执行 php -r "var_dump(extension_loaded('ffi'));" 验证真实加载状态;若返回 false,说明该 PHP 版本未编译支持 FFI(尤其 PHP 7.4 多数预编译包默认不启用),须升级至 PHP 8.1+ 或更换支持 FFI 的构建版本。

check-platform-reqs 会报 ext-ffi 缺失,但 php -m 看得见
这是典型的 PHP CLI 配置路径错位问题。composer check-platform-reqs 读的是当前 CLI 进程实际加载的 php.ini,不是你编辑的那个文件。比如 macOS 上用 Homebrew 装了 PHP 8.2,但 PHP_BINARY 环境变量仍指向系统旧版(/usr/bin/php),而该版本没启用 ffi 扩展——php -m 可能显示它存在,但那是 Apache 或另一个 PHP 实例的模块列表。
验证方式很简单:
- 运行
php --ini,看 Loaded Configuration File 路径是否和你预期一致 - 接着执行
php -r "var_dump(extension_loaded('ffi'));",输出bool(true)才算真正加载成功 - 如果
php -m | grep ffi有结果,但上面命令返回false,说明 CLI 和 Web SAPI 加载了不同配置
PHP 7.4 默认不带 FFI,不能靠 php.ini 开启
FFI(Foreign Function Interface)从 PHP 7.4 开始作为实验性扩展引入,但默认是禁用的,且必须在编译时启用(--with-ffi)。很多预编译包(如 Ubuntu 官方源、宝塔面板的 PHP 7.4)压根没编译这个模块,光在 php.ini 里加 extension=ffi 会直接报错:PHP Warning: Unable to load dynamic library 'ffi' (tried: .../ffi.so)。
确认是否支持 FFI 的唯一可靠方式是:
立即学习“PHP免费学习笔记(深入)”;
-
php -r "echo defined('FFI') ? 'yes' : 'no';"—— 返回yes才代表可用 -
php -i | grep -i ffi—— 查看是否有ffi support => enabled - 若两者都否,说明当前 PHP 二进制根本不支持 FFI,换版本或重编译是唯一解
项目 require ext-ffi 但本地 PHP 7.4 不支持,怎么办
别硬改 composer.json 删掉 "ext-ffi": "*",也别盲目加 --ignore-platform-req=ext-ffi。FFI 是底层能力,删了可能让依赖包(比如某些加密库、RPC 客户端)直接无法初始化。
更务实的做法是:
- 优先升级 PHP CLI 到 8.1+:FFI 在 8.1 后转正,默认开启,
php -r "echo FFI::cdef('');"就能跑通 - 若必须卡在 7.4,检查项目是否真需要 FFI —— 有些包只是声明了可选依赖,实际代码路径未触发;可临时注释掉相关功能再试
- CI/CD 场景下,用
composer config platform.ext-ffi 1告诉 Composer “假装有”,但务必同步在运行环境部署真实支持的 PHP 版本
为什么 --ignore-platform-req=ext-ffi 成功后运行时报 Class 'FFI' not found
因为 --ignore-platform-req=ext-ffi 只跳过 Composer 安装阶段的校验,不解决运行时缺失。PHP 解析器根本找不到 FFI 类定义,这不是 autoload 或命名空间问题,是扩展层空缺。
常见连锁反应:
- Composer 装完包,
vendor/autoload.php加载正常,但第一次调用FFI::cdef()就 Fatal error -
composer dump-autoload不报错,但php -d extension=ffi.so index.php才可能起作用(前提是你的 PHP 支持动态加载) - 某些 Docker 镜像(如
php:7.4-cli)默认没编译 FFI,docker-php-ext-install ffi会失败,得换基础镜像
真正要动的不是 Composer 参数,而是 PHP 本身——要么换支持 FFI 的版本,要么确认当前二进制确实内置了该模块。否则所有绕过手段都是掩耳盗铃。



















