Composer 不支持 PHP 扩展版本约束,因其仅做存在性检查且扩展无语义化版本;应通过 platform 锁定 PHP 版本、require 声明扩展存在,并在运行时用 defined() 或 function_exists() 检测具体功能。

Composer 本身不管理 PHP 扩展的版本,它只检查 ext-json、ext-dom 等扩展是否已加载,且仅支持布尔式判断(存在 / 不存在),不支持类似 "ext-json": "^7.4" 这样的版本约束。
为什么 composer.json 中的 ext-* 条件无法指定扩展版本?
PHP 扩展没有语义化版本号体系,phpversion('json') 返回空字符串或不可靠值(如 libjson 版本),Composer 的 platform 机制仅校验扩展是否启用,而非其内部实现版本。这意味着:
-
"ext-json": "*"和"ext-json": ">=1.0.0"效果完全相同——只要扩展存在就通过 -
"ext-dom": "^2.0"不会报错,但也不会做任何版本比对,纯属无效写法 - 某些旧版 PHP(如 7.2)中
ext-json缺少JSON_INVALID_UTF8_IGNORE常量,但 Composer 完全感知不到
实际兼容性问题必须在运行时检测
真正影响行为的是扩展功能可用性,而非“是否存在”。例如:ext-json 在 PHP 7.3+ 才支持 JSON_THROW_ON_ERROR;ext-dom 在 PHP 8.0+ 才默认启用 DOMDocument::loadHTML() 的严格错误报告。这类问题只能在代码中显式判断:
if (!defined('JSON_THROW_ON_ERROR')) {
throw new RuntimeException('ext-json must support JSON_THROW_ON_ERROR (PHP >= 7.3)');
}
$doc = new DOMDocument();
if (!method_exists($doc, 'registerNodeClass')) {
throw new RuntimeException('ext-dom is too old; missing DOMDocument::registerNodeClass (PHP >= 5.3.0 but often broken before 7.0)');
}
更稳妥的做法是使用 function_exists() 或 defined() 检查具体能力,而不是依赖扩展名和模糊版本。
立即学习“PHP免费学习笔记(深入)”;
如何在 composer.json 中合理声明平台依赖?
唯一可靠的方式是用 platform 锁定最低 PHP 版本,并在 require 中声明扩展存在性,作为基础门槛:
{
"require": {
"php": ">=7.4",
"ext-json": "*",
"ext-dom": "*"
},
"config": {
"platform": {
"php": "7.4.33"
}
}
}注意以下几点:
-
platform.php仅用于本地开发模拟,不影响真实环境检测 - CI 流程中应使用真实 PHP 版本运行
composer install --no-interaction,让 Composer 报出缺失扩展的错误 - 不要在
require中写"ext-json": ">=1.0",这毫无意义,还可能误导协作者
最易被忽略的一点:即使 Composer 通过了 ext-dom 检查,PHP 8.0+ 默认开启 libxml 严格模式,导致 DOMDocument::loadHTML() 对 malformed HTML 抛出 Warning 而非静默修复——这种行为差异必须在业务代码里用 @ 抑制或 libxml_use_internal_errors(true) 处理,跟 Composer 无关。











