Composer支持在require字段中使用ext-xxx语法声明PHP扩展依赖,xxx需与php -m输出的扩展名完全一致(小写、无下划线、无后缀),版本号只能为"*"或空,用于安装时校验而非自动安装。

require中怎么写PHP扩展依赖
Composer 不支持在 require 字段里直接写 PHP 扩展名(比如 "ext-curl": "*" 是无效的)。它只认包名(如 "monolog/monolog"),不解析扩展。真正用来声明扩展依赖的是 require 的兄弟字段:require-dev 和更关键的 config.platform —— 但都不是这里要的答案。
正确位置是 composer.json 根级的 require 下,用特殊命名空间:ext-xxx。这个语法是 Composer 原生支持的伪包名,不是插件或约定,而是内建机制。
实操时注意以下几点:
-
ext-xxx中的xxx必须和php -m输出的扩展名完全一致(小写、无下划线、无版本后缀),例如ext-mbstring、ext-pdo_mysql、ext-xml - 版本号只能写
*或留空("ext-curl": "*"或"ext-curl": "^7.4"都不行;"ext-curl": ""等价于"*") - 它只影响
composer install/update时的依赖解析:如果目标环境没装该扩展,Composer 会报错并中止,而不是静默跳过 - 不会自动安装扩展——它只是校验,不是包管理器本身
为什么写了 ext-xxx 还不报错?
常见现象:加了 "ext-gd": "*",但本地没装 GD,composer install 却成功了。这不是 Composer 失效,而是你可能踩了这几个坑:
立即学习“PHP免费学习笔记(深入)”;
- 没运行
composer update或composer install --ignore-platform-reqs(后者会跳过所有平台检查,包括扩展) - 用了
config.platform.ext-gd = false(这相当于告诉 Composer “假装 GD 不存在”,常用于 CI 环境模拟低配环境) - PHP CLI 和 Web SAPI 加载的
php.ini不同:你在终端跑php -m | grep gd有结果,但 Composer 实际调用的是另一个 PHP 配置(比如 Docker 容器里没挂载 ini 文件) - 扩展名拼错了:比如写成
ext-gd2(不存在)、ext-GD(大小写敏感)、ext-gd.so(带后缀错误)
ext-xxx 和 platform.php 的区别
ext-xxx 是运行时依赖声明,面向“我的代码必须用到这个扩展”;而 config.platform.php 是构建时目标环境声明,面向“我打包的包要兼容 PHP 8.1”。两者定位不同,不能互相替代。
典型误用场景:
- 想让包在 PHP 7.4 上也能装,却只加
"ext-json": "*"—— 没用,因为ext-json在 PHP 7.4 是内置的,但如果你的代码用了JSON_THROW_ON_ERROR(PHP 7.3+),就得靠"platform": {"php": "7.4"}触发 Composer 对语言特性的兼容性检查 - 在
platform里写"ext-redis": "5.3.7"—— 无效,platform只接受php、ext-xxx(值只能是true/false),不支持版本号 - 同时设
"ext-openssl": "*"和"platform": {"ext-openssl": false}—— 后者优先,Composer 会忽略扩展要求
CI/CD 中如何安全校验扩展
在 GitHub Actions、GitLab CI 等环境里,光靠 composer install 不一定能暴露问题,因为默认 PHP 镜像往往预装了大量扩展。要真实模拟用户环境,得主动控制:
- 用最小化镜像,例如
php:8.2-cli-slim,然后显式docker run ... apt-get install -y libpng-dev && docker-php-ext-install gd - CI 脚本开头加校验:
php -m | grep -E '^(curl|mbstring|xml)$' || (echo "Missing required extensions"; exit 1)
- 在
composer.json里补全所有硬依赖:哪怕ext-json是内置的,也建议显式写出,避免某些嵌入式 PHP 移除它 - 别依赖
composer validate检查扩展 —— 它只校验 JSON 结构,不验证ext-xxx是否合法
最易被忽略的一点:扩展依赖是「传递性」的。你自己的包声明了 ext-zip,但下游项目 require 了你,却没在自己 composer.json 里重复声明,那它的 composer install 仍会失败 —— Composer 不会自动合并上游的扩展要求。每个项目都得自己写清楚。



















