应将“ext-posix”从require移至require-dev,或用if (function_exists('posix_getpid')){}运行时判断;临时可加--ignore-platform-req=ext-posix,但CI中必须用目标平台生成composer.lock并配置config.platform。

composer install 在 Windows 上报 “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,但千万别提交进composer.lock或 CI 脚本
config.platform 写了却没生效?
config.platform 只影响 composer update 时的依赖解析,对 composer install 完全无效——它只照着 composer.lock 还原,根本不看你当前配置。
- 必须放在
composer.json的"config": {}下,不能放顶层 - 扩展名必须带
ext-前缀,且大小写、连字符要和php -m输出完全一致(ext-xdebug✅,ext-xdebg❌) - 改完后必须执行
composer update --lock(或composer update),否则composer.lock仍是旧规则锁定的 - CI 流水线里执行
composer install前,确保composer.lock是用目标平台配置生成的
scripts 字段里的 shell 命令为什么一到 Windows 就挂
scripts 字段是纯 shell 命令,Composer 不翻译、不兼容、不模拟。Windows 的 cmd.exe 和 Linux/macOS 的 bash 对语法、路径分隔符、工具链的支持完全不同。
- 别写
cp、rm -rf、ls、grep—— 这些在 Windows 原生命令行里根本不存在 - 路径拼接统一用正斜杠
/,PHP 7.4+ 会自动转义,别用DIRECTORY_SEPARATOR动态替换 - 需要删文件、复制资源?改用 PHP 原生函数:
RecursiveDirectoryIterator+FilesystemIterator,或copy()+unlink() -
bin-compat=full只控制生成.bat/.sh包装器,不重写脚本逻辑;执行前务必在干净 Windows 环境下验证
如何让打包产物在多系统上行为一致
核心不是让 Composer “识别系统”,而是控制它“按目标环境选包” + “避免运行时硬依赖”。跨平台打包最常被忽略的一点是:composer.lock 文件本身必须由目标平台生成并提交,而不是开发者本地生成后就认为通用。
- 删除
composer.json中对平台扩展的硬性require(如"ext-posix": "*"),改用运行时判断 - 在
config段显式声明目标平台:"platform": {"php": "8.2.12", "ext-gd": "8.2.12"} - 对含二进制分发的包(如
spatie/browsershot或symfony/cli),优先用官方 PHAR 安装方式,而非依赖 Composer 的bin自动注册 - CI 构建脚本中,先
composer update --lock(用目标平台 PHP + 扩展),再composer install,顺序不能反


















