platform是composer在依赖解析阶段模拟php环境的配置,只影响composer install/update选包逻辑,不改变php -v输出或运行时行为,必须写在composer.json的config.platform下且值为对象。

Composer 本身不区分操作系统,所谓“不同系统依赖差异”其实是包作者通过 ext-* 或 php 版本约束实现的平台感知;真正可控的手段只有 config.platform —— 它不改变运行时行为,只影响 install 和 update 阶段的依赖解析逻辑。
为什么 platform 能解决跨系统依赖问题
某些包(如 phpunit/phpunit、roave/security-advisories)在 require 中声明了 ext-xdebug 或 ext-pcntl,而这些扩展在 Windows 上默认不可用、macOS 上可能未启用、Linux 上又版本不一。Composer 不会主动跳过它们,而是直接报错:Your requirements could not be resolved。
这时你不是要“让 Composer 识别系统”,而是要告诉它:“别查我本地有没有 ext-xdebug,就当我有”。这就是 config.platform 的作用。
-
config.platform.php覆盖当前 PHP 版本判断,影响所有php >= x.y约束 -
config.platform.ext-*(如ext-gd、ext-redis)声明扩展“已存在”,跳过扩展检测 - 该配置只写在
composer.json的config字段下,不能放顶层,也不能用字符串代替对象 - 它对
composer install和composer update生效,但不影响运行时加载
常见错误写法与修正示例
错误配置比正确配置更常出现,尤其在 CI/CD 流水线中导致反复失败:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- ❌ 把
platform写成顶层字段:"platform": { "php": "8.1" }→ 必须嵌套在"config": {}里 - ❌ 使用模糊版本号:
"ext-gd": "^8.1"→platform只接受具体版本(如"8.1.0")或布尔值true - ❌ 拼错扩展名:
"ext-xdebg"→ 扩展名必须与php -m输出完全一致(注意大小写和连字符) - ✅ 正确写法示例:
{
"config": {
"platform": {
"php": "8.1.25",
"ext-xdebug": true,
"ext-pcntl": true,
"ext-posix": true
}
}
}
生产部署时如何安全绕过平台检查
开发机装了 xdebug,但线上服务器没装,且你确定 require-dev 里的包(如 phpunit)不会被线上代码调用 —— 这时不该靠 platform “伪造”扩展,而应关闭校验:
- 用环境变量关闭:设置
COMPOSER_PLATFORM_CHECK=0,再执行composer install --no-dev - 或命令行参数:直接运行
composer install --no-dev --ignore-platform-reqs - ⚠️ 注意:
--ignore-platform-reqs会跳过所有平台检查(包括php版本),仅建议在明确控制环境时使用 - 更推荐的做法是:开发环境用
platform模拟线上缺失的扩展,线上用COMPOSER_PLATFORM_CHECK=0关闭校验,职责分离更清晰
多环境 CI 构建中 platform 的实际用法
一个项目需同时构建 CentOS、Ubuntu、Windows runner,但所有环境都跑 PHP 8.1 —— 你不希望因某个 runner 缺少 ext-sockets 就中断整个流水线:
- 在
composer.json中固定声明:"ext-sockets": true,让所有环境都按“已安装”解析依赖 - CI 脚本中无需改配置,直接
composer install --no-dev即可 - 若某环境真需要禁用某扩展(如 Windows 上不用
pcntl),就在该环境的部署命令前加COMPOSER_PLATFORM_CHECK=0,而不是删掉platform - 切记:只要
composer.lock是在统一platform下生成的,所有环境执行install就能复现相同依赖树
真正容易被忽略的是:platform 配置一旦写进 composer.json,就成为项目契约的一部分;它不解决“运行时报错”,只解决“装不上”。如果线上缺扩展却硬要加载对应功能,崩溃仍会发生——那得靠运行时检测(如 extension_loaded())兜底,不是 Composer 的事。










