composer 不支持按操作系统条件安装依赖,ext-inotify 等系统专属扩展不可写入 require,否则跨平台安装会因解析失败而中断;应通过 config.platform 临时绕过校验,并在运行时用 php_os_family 和 extension_loaded() 显式判断。

Composer 本身不支持按操作系统条件安装依赖,硬把 ext-inotify 这类 Linux 专属扩展写进 require,Windows 或 macOS 上执行 composer install 就会直接失败,报 “Your requirements could not be resolved” —— 不是网络问题,也不是权限问题,是 Composer 在解析阶段就拒绝了。
为什么 ext-inotify 不能写在 require 里
这类扩展只存在于特定系统(如 ext-inotify 仅 Linux、ext-pcntl 默认禁用在 Windows),而 require 字段表达的是“所有环境都必须满足”的硬约束。Composer 安装时会校验当前 PHP 环境是否满足全部 require 条件,不满足就中断,不会跳过或降级。
- 错误现象:
Your requirements could not be resolved to an installable set of packages. ext-inotify is missing from your system. - 常见误操作:把仅用于 CLI 工具的扩展(如
ext-pcntl)放进require而非require-dev -
config.platform是唯一能“假装”存在扩展的地方,但只影响依赖解析,不改变运行时行为
config.platform 的正确写法和局限
它只能让 Composer 在安装时忽略某些扩展缺失,但无法让代码在不支持的系统上真正运行。必须严格遵循格式,否则静默失效。
- 路径必须是
config.platform,不是根级platform或config下其他位置 - 值必须是字符串,不能带版本运算符:
"ext-inotify": "0"✅,"ext-inotify": "*"❌,"ext-inotify": "^1.0"❌ - 它只影响依赖解析,不解决运行时
extension_loaded('inotify')返回false的问题 - CI 环境若跨平台(如 GitHub Actions 同时跑 Ubuntu/Windows),仍需配合运行时判断,否则部署后直接 fatal error
运行时检测才是跨平台兼容的关键
把 OS 或扩展适配逻辑从“安装时”移到“运行时”,才能真正安全。Composer 只管装包,不负责执行逻辑是否成立。
- 在代码中显式检查:
if (PHP_OS_FAMILY === 'Linux' && extension_loaded('inotify')) { /* use inotify */ } - 避免在
autoload或全局初始化阶段调用 OS 专属函数,防止 Windows 下直接报错 - CLI 工具类包建议把 OS 专属功能拆成独立命令,通过
scripts或子命令隔离,而非启动即加载 - 测试时用
php -n(禁用所有扩展)模拟最小环境,验证 fallback 路径是否可用
别碰 require-dev 的 OS 陷阱
很多人以为放到 require-dev 就万事大吉,其实不然——只要 CI 或本地执行了 composer install --no-dev,这些扩展就不会被检查;但一旦执行 composer install(默认含 dev),同样会触发校验失败。
- 真正安全的做法:dev 依赖也应可选,比如用
symfony/process替代直接调用pcntl_fork() - 如果必须用原生扩展,文档里明确标注“仅限 Linux”,并在
README中说明 Windows 用户应改用 Docker 或 WSL - 警惕 IDE 自动补全或旧模板残留的
ext-*条目,它们常被忽略,直到某次 CI 失败才暴露
最易被忽略的一点:即使你用了 config.platform 让安装通过,只要代码里没做 extension_loaded() 检查,上线后在不支持的系统上照样 crash。Composer 解决不了运行时环境差异,它只负责把文件放对地方。











