composer check-platform-reqs --no-dev 是定位扩展缺失最准的起点,但它只告诉你“缺什么”,不告诉你“为什么缺”——真正卡住脚本运行的,往往是 cli 与 web 环境错位、php 二进制路径不一致、或扩展虽加载但底层库(如 icu)不兼容。

直接说结论:composer check-platform-reqs --no-dev 是定位扩展缺失最准的起点,但它只告诉你“缺什么”,不告诉你“为什么缺”——真正卡住脚本运行的,往往是 CLI 环境和 Web 环境错位、PHP 二进制路径不一致、或扩展虽加载但底层库(如 ICU)不兼容。
为什么 check-platform-reqs 显示 MISSING,但 php -m 能看到扩展?
这不是 Composer 报错错了,而是你执行 php -m 和 Composer 实际调用的不是同一个 PHP 二进制文件。
- 先跑
which php,再用这个完整路径执行检查:比如/usr/bin/php -m | grep zip,而不是只敲php -m - macOS 上 Homebrew 安装的 PHP 常被系统自带旧版覆盖 PATH,
php -v看到的是新版本,但 Composer 启动时用的是/usr/bin/php(不带 zip) - Linux 多源共存(apt + 源码编译)时,不同 PHP 的
extension_dir指向不同目录,.so文件放错位置就等于没装 - Windows 下注意
php.ini中写的是extension=php_zip.dll还是extension=zip,两者在不同 PHP 版本中有效形式不同
check-platform-reqs 通过了,但脚本运行仍报 Class not found 或 function undefined
说明扩展“加载成功”,但功能不可用——常见于依赖底层库的扩展(如 ext-intl、ext-gd)。
-
ext-intl即使php -m | grep intl有输出,也可能因 ICU 主版本不匹配被静默拒绝:运行php -i | grep 'ICU version'查 PHP 编译绑定的 ICU 版本,再用pkg-config --modversion icu-i18n(Linux)或brew info icu4c(macOS)查系统 ICU 版本,二者主版本号必须一致(如都是 72 或都是 74) -
ext-gd缺少 FreeType 或 JPEG 支持时,gd_info()返回的freetype或jpeg字段为false,但extension_loaded('gd')仍返回true -
ext-openssl在 Windows 上常因php_openssl.dll依赖的libeay32.dll/ssleay32.dll缺失而运行时报错,check-platform-reqs完全不检测这类 DLL 依赖
怎么确认扩展真能用,不止是“加载了”?
别只信 php -m 或 extension_loaded(),要模拟脚本实际调用路径。
- 对
ext-zip:运行php -r "new ZipArchive();",不报错才算可用 - 对
ext-pdo_mysql:运行php -r "new PDO('mysql:host=localhost', '', '');",看是否抛出连接异常(不是扩展缺失异常) - 对
ext-mbstring:运行php -r "var_dump(mb_detect_encoding('测试'));",返回非false才算生效 - Docker 用户额外注意:
apk add php82-zip后必须加RUN docker-php-ext-enable zip,Alpine 不自动写.ini文件
最容易被忽略的点是:扩展名、PHP 版本号、配置文件路径、底层库版本,这四者必须全部对齐。改完 php.ini 不重启终端、装了包却没配 extension_dir、CLI 和 Web 共用一个扩展但不同 php.ini ——这些细节一错,check-platform-reqs 就会给出虚假安全感。











