Composer install 在 CI 上报“required PHP extension xyz missing”错,因它默认按本地环境解析依赖而非目标环境;platform 配置须写在 composer.json 的 config 段中,显式声明目标 PHP 版本与扩展,仅影响依赖解析。

为什么 composer install 在 CI 上报错 “required PHP extension xyz missing”?
因为 Composer 默认按当前运行环境(比如你本地 PHP 8.2 + ext-redis)解析依赖,但 CI 或生产环境可能是 PHP 7.4 且没装 ext-redis。它不是“检测目标环境”,而是“信任当前环境”。platform 就是用来显式声明“我最终要跑在什么 PHP 版本和扩展上”的机制。
platform 配置写在哪?怎么写才生效?
必须写在 composer.json 的 config 段里,不是 require 或 require-dev。它只影响依赖解析阶段,不安装任何东西。
常见写法:
{
"config": {
"platform": {
"php": "7.4.33",
"ext-gd": "8.1.0",
"ext-mbstring": "8.1.0",
"ext-redis": "5.3.7"
}
}
}
注意:ext-xxx 的版本号可以写 *(表示“只要存在就行”),但部分包(如 symfony/cache)会检查扩展版本是否 ≥ 某值,这时写死更稳妥。
- PHP 版本必须严格匹配目标环境的
php -v输出主版本+次版本(如8.1.27),否则可能选错包分支 - 扩展名大小写敏感:
ext-curl✅,ext-CURL❌ - 如果只配
"php": "8.1"不带小版本,Composer 会按语义化版本规则解释为^8.1,可能意外允许8.2解析结果
配置了 platform 还是装不上包?检查这三点
最常见原因不是配置错,而是没触发平台约束逻辑:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
composer update时,platform仅影响新解析的依赖树;已有composer.lock会优先沿用其中记录的版本 —— 必须加--with-all-dependencies或删 lock 文件重装 - 用了
composer install --ignore-platform-reqs(CI 脚本里常有),这个 flag 会直接无视platform配置 - 某些包通过
provide声明虚拟扩展(如symfony/polyfill-mbstring提供ext-mbstring),此时platform中的ext-mbstring可能被绕过 —— 真实环境没扩展时,polyfill 不一定能完全替代
PHP 版本和扩展不一致时,platform 怎么取舍?
没有取舍 —— 它必须反映真实部署环境的最小交集。例如:
你的应用要同时跑在阿里云函数(PHP 8.0 + ext-redis)和某老 CentOS(PHP 7.4 + 无 ext-redis),就不能在 platform 里写 "ext-redis": "*",否则 composer install 在 7.4 环境会失败。正确做法是:要么放弃 redis 功能、改用文件缓存;要么把 redis 相关代码隔离进可选的 require-dev 或插件机制。
真正容易被忽略的是:扩展的 ABI 兼容性。比如 ext-redis 5.3.7 在 PHP 8.0 和 8.1 下二进制不兼容,即使 platform 写了 "php": "8.0",也得确保扩展版本与 PHP 版本实际匹配 —— platform 不校验这个,只管 Composer 解析逻辑。










