config.platform 仅用于声明预期运行环境而非指定目标架构,它只在 composer update 时影响依赖解析,对 install 无效;必须配合 --lock 更新 lock 文件才能生效,且不能替代 Docker 等跨平台构建工具。

config.platform 不能指定目标架构,只能模拟运行时环境
Composer 本身不支持在 composer install 或 composer require 时通过参数指定目标 CPU 架构(如 arm64、amd64)或操作系统(如 win-x64)。它只读取当前 PHP 进程的 PHP_VERSION、extension_loaded() 等信息,并据此解析依赖树 —— 换句话说,它“看的是你正在跑的环境”,不是“你要部署到哪”。
真正能影响依赖选择的,只有 config.platform。但它不是“构建指令”,而是“声明预期环境”的方式:告诉 Composer “请按这个平台来选包”,从而避免本地 PHP 版本过高导致装入不兼容的依赖。
-
config.platform必须写在composer.json的"config": {}下,不能放顶层 - 扩展名必须带
ext-前缀,且大小写、连字符要和php -m输出完全一致(ext-pdo_mysql✅,ext-pdo-mysql❌) - 值只要非空即视为存在(
"true"、"8.1.0"都行),Composer 不校验版本号是否真实匹配 - 改完后必须执行
composer update --lock,否则composer.lock仍按旧 platform 解析结果锁定
为什么 ext-posix 报错不是 Composer 的锅
你在 Windows 上执行 composer install 时看到 ext-posix missing,不是 Composer 故意卡你,而是某个依赖(常见于 symfony/console 旧版、phpunit/phpunit 或 CLI 工具)在 require 中写了 "ext-posix": "*"。Windows 没这个扩展,PHP 加载不了,Composer 就直接拒绝解析整个依赖树。
- 先定位谁加的:
composer show --tree | grep posix - 如果只是开发时用(比如本地跑测试),把它从
require移到require-dev更合理 - 如果必须运行,代码里改掉硬调用:
if (function_exists('posix_getpid')) { ... },而不是无条件调用 - 临时绕过可用
composer install --ignore-platform-req=ext-posix,但别提交进 CI 或composer.lock
platform 配置对 install 无效,只对 update 生效
config.platform 不会改变 composer install 的行为 —— 它只在 composer update(或带 --lock 的 update)时参与依赖解析。这意味着:如果你已经有一个 composer.lock,哪怕你改了 platform,install 依然照着 lock 文件里的版本装,完全不看你新写的 platform。
- 想让 platform 生效,必须先
composer update --lock(推荐)或composer update --dry-run看效果 - CI/CD 中应确保每次构建前都基于目标 platform 执行一次
update --lock,再 commit 新的 lock 文件 - 不要指望
composer install --ignore-platform-reqs能解决跨平台问题 —— 它只是跳过检查,不保证装上的包真能在目标机器上跑
真正跨平台构建得靠外部工具,不是 Composer
Composer 是依赖解析器,不是构建器。它不编译、不打包、不生成二进制。所谓“适配 arm64”或“Windows 兼容”,最终得靠:
- Docker:用
FROM --platform=linux/arm64启动对应架构容器,再跑composer install - 预编译二进制:比如
spiral/roadrunner提供各平台 release,Composer 只负责下载,不参与编译 - 包自身平台感知逻辑:例如
psy/psysh在 runtime 判断PHP_OS_FAMILY决定加载哪个 readline 实现 - 脚本层隔离:把
cp、rm -rf这类 shell 命令换成 PHP 原生函数(copy()、rrmdir()),避免平台差异
硬要在 composer.json 里塞架构相关逻辑,只会让依赖树变得不可预测 —— 因为 Composer 根本没能力识别 arm64,它连 php_uname('m') 都不调用。


















