composer check-platform-reqs 仅校验 composer.json 中显式声明的 PHP 版本与扩展是否在当前 CLI 环境中可用,不检查未声明依赖、Web 环境、扩展底层库或运行时实际功能,故通过≠可运行。

直接说结论:composer check-platform-reqs 不是“确保扩展就绪”的万能开关,它只检查 composer.json 里**显式声明**的 PHP 版本和扩展是否在当前 CLI 环境中可用。没声明 = 不查,声明了但扩展没加载 = 报 missing,而你运行 php -m 看到的 zip,可能根本不是 Composer 正在用的那个 PHP。
为什么 check-platform-reqs 显示 ext-zip: * (missing),但 php -m 能看到 zip?
这不是扩展没装,而是 Composer 和你执行 php -m 时调用的不是同一个 PHP 二进制文件。
- 运行
which php查看当前 shell 默认的 PHP 路径,再用这个路径执行/usr/bin/php -m | grep zip或/opt/homebrew/bin/php -m | grep zip—— 必须用和 Composer 完全一致的路径 - macOS 上 Homebrew 安装的 PHP 常被系统自带旧版(不带 zip)覆盖 PATH,
php -v看到的是新版本,但 Composer 启动时用的是/usr/bin/php - Linux 下不同 PHP 源(apt 包 vs 源码编译)的
.so文件路径不同,CLI 和 Web SAPI 加载的扩展也不同,check-platform-reqs只管 CLI 环境
check-platform-reqs 真正检查什么,又完全不管什么?
它只读 composer.json 的 require 和 config.platform 字段,然后调用 extension_loaded() 做运行时判断 —— 仅此而已。
- ✅ 检查:你写了
"php": ">=8.1",就比对真实 PHP 版本;写了"ext-zip": "*",就调用extension_loaded('zip') - ❌ 不检查:代码里实际用了
openssl_encrypt(),但composer.json没声明ext-openssl—— 这种漏声明,check-platform-reqs完全沉默 - ❌ 不检查:Web 环境(如 Nginx + PHP-FPM)是否启用同名扩展,
phpinfo()页面必须单独打开确认 - ❌ 不检查:扩展虽加载,但依赖的底层库缺失(如
ext-intl缺 ICU),运行时仍会崩
怎么让 check-platform-reqs 输出真正有用?
关键不是多跑几遍命令,而是先规范声明需求,再用对工具验证。
- 在
composer.json的require里补全最低要求:"php": ">=8.1.0"(别用^8.1,check-platform-reqs对范围符支持弱) - 显式列出项目硬依赖的扩展:
"ext-zip": "*"、"ext-pdo_mysql": "*"、"ext-mbstring": "*" - 用
composer show --platform替代php -m—— 它输出的是 Composer 实际识别到的已启用扩展,过滤掉仅注册未初始化的“幽灵扩展” - CI/CD 中可配
"platform": {"php": "8.2.10"}模拟目标环境,但本地开发建议禁用,否则会掩盖真实兼容问题
比 check-platform-reqs 更早暴露问题的办法
静态检查只能告诉你“声明是否满足”,不能代替一次轻量级运行验证。
-
composer install --dry-run:走完整依赖解析 + 平台校验流程,不写文件,比check-platform-reqs更贴近真实安装逻辑 - Web 环境务必访问
phpinfo()页面,确认opcache、apcu等需手动启用的扩展确实 loaded - 如果项目用了 Docker 或宝塔,每个 PHP 版本的扩展要单独勾选启用 —— “装一次,全版本生效” 是错觉
最容易被忽略的一点:check-platform-reqs 的 OK 输出,只代表你声明的东西都齐了,不代表代码能跑通。上线前别只信它。











