check-platform-reqs在docker或ci中报错但实际能跑,根本原因是它默认校验当前shell下的php环境(如宿主机mac的php 8.1),而非目标运行环境(如容器内php 8.3);必须将命令执行于目标环境(如docker exec、ci runner或docker-compose run),否则结果不可信。

check-platform-reqs 为什么在 Docker 或 CI 里报错但实际能跑
根本原因不是环境真不兼容,而是 check-platform-reqs 默认读取的是**当前 shell 下的 PHP 环境**,而非目标运行环境。比如你在 macOS 宿主机上执行该命令,它检查的是 Mac 自带或 Homebrew 装的 PHP(可能是 8.1),但项目实际部署在 Alpine Linux 的 PHP 8.3 容器里——结果自然错得离谱。
常见虚假报错现象:
-
ext-pdo_mysql missing:宿主机没装 MySQL 扩展,但容器镜像里已启用 -
php version mismatch:宿主机是 PHP 8.2,composer.json写了"php": "^8.3",但 CI 构建用的是 8.3 镜像 -
lib-curl not found:宿主机 curl 版本旧,但容器里是新版 musl 编译的 libcurl
这不是 bug,是设计使然:check-platform-reqs 只做本地环境快照比对,不感知目标平台。
怎么让 check-platform-reqs 检查目标环境而非宿主机
必须把命令“挪”到目标环境中执行,而不是在本地敲。有三种可靠方式:
- 进容器执行:
docker exec -it myapp-php php -d memory_limit=-1 /var/www/composer check-platform-reqs - CI 中指定 runner 环境:GitHub Actions 用
ubuntu-latest+ PHP setup action 安装对应版本后,再跑composer check-platform-reqs - 用
--platform参数伪造目标环境(仅限验证依赖解析):composer check-platform-reqs --platform=php:8.3 --platform=ext-pdo_mysql:* --platform=ext-mbstring:*—— 注意:这不会改变扩展加载状态,只影响版本和扩展名存在性判断
别用 config.platform 替代,它只影响 install/update 阶段的包选择逻辑,对 check-platform-reqs 无效。
交叉编译下 check-platform-reqs 的真实价值在哪
它只在两个场景真正有用:
- CI 流水线中,在
composer install前校验构建镜像是否满足composer.json声明的平台要求(此时命令已在目标镜像内执行) - 本地开发时,用
docker-compose run --rm php composer check-platform-reqs快速确认 docker-compose.yml 里定义的 PHP 服务是否启用了所需扩展
它不检查预编译二进制(如 Puppeteer、Sodium 的 .so)、不校验扩展 ABI 兼容性、也不管 lib-xxx 库的 soname 版本——这些得靠运行时测试或 ldd vendor/bin/xxx 手动验证。
容易被忽略的细节:PHP CLI 和 Web SAPI 扩展不一致
很多报错源于 CLI 和 FPM 加载的 php.ini 不同。比如 php -m | grep mbstring 显示有,但 check-platform-reqs 仍报缺失——说明它读的不是这个 php.ini。
验证方式:
- 运行
php --ini,看 Loaded Configuration File 路径 - 对比
php -r "print_r(get_loaded_extensions());"和php -c /path/to/fpm/php.ini -r "print_r(get_loaded_extensions());" - Dockerfile 中确保
RUN docker-php-ext-install mbstring后,CLI 和 FPM 的php.ini都包含extension=mbstring.so
跨平台项目里,最常掉坑的地方不是 PHP 版本,而是扩展加载路径和 ini 文件归属搞混了。











