composer-merge-plugin 已被官方弃用,因其绕过 Composer 原生依赖解析导致锁文件不一致、版本冲突、CI 失败及 PHP 8.2+ 兼容性问题;应改用 repositories + config.platform 或环境化脚本方案。

composer-merge-plugin 已被官方明确弃用,且 Composer 本身不支持运行时合并多个 composer.json 文件。你看到的“动态合并插件”效果,基本都来自过时实践或对插件机制的误读——这不是 Composer 的设计目标,强行依赖它会带来锁文件不一致、CI 失败、本地与生产环境行为差异等真实故障。
为什么 composer-merge-plugin 必须停用
维基媒体基金会早在 2023 年起就停止维护该插件,Composer 2.2+ 版本已出现兼容性断裂;更关键的是,它绕过 Composer 原生依赖解析流程,直接拼接 JSON 后触发安装,导致:
-
composer.lock中记录的依赖图与实际安装结果可能不匹配(尤其在递归合并子目录配置时) - 当两个被合并的配置同时 require 同一个包但版本约束冲突(如
"monolog/monolog": "^2.0"vs"monolog/monolog": "^3.0"),插件默认“后覆盖前”,但 Composer 本身不会校验这种覆盖是否满足语义化版本兼容性 - PHP 8.2+ 环境下,插件内部反射调用部分已被废弃的 Composer 内部类,引发
Deprecated: Creation of dynamic property ...报错 - GitHub Actions 或 GitLab CI 中执行
composer install --no-interaction时,因插件 hook 触发时机不稳定,偶发跳过合并步骤
替代方案:用 repositories + config.platform 实现多平台适配
真正可控的“多平台整合”,不是靠合并配置,而是靠声明式约束和隔离式解析:
- 把各平台专用逻辑(如 Windows 下需
ext-xdebug调试、Linux 下需ext-pcntl进程控制)统一收口到独立私有包中,例如myorg/platform-windows和myorg/platform-linux - 在主项目
composer.json中通过repositories指向这些包,并用require按需引入:"myorg/platform-linux": "dev-main" - 用
config.platform显式锁定目标环境能力,避免本地开发机 PHP 版本过高导致依赖解析出错:{"php": "8.1.27", "ext-pcntl": "8.1.27"} - 所有平台相关扩展(如
ext-gd、lib-curl)必须写进require,而非仅靠文档提醒——Composer 会在install阶段做存在性检查并报错
需要动态加载配置?改用 extra 字段 + 自定义脚本
如果你的真实需求是“根据环境变量加载不同依赖集”,不要碰任何合并插件,而应利用 Composer 原生支持的钩子机制:
- 在
composer.json的extra字段里存环境标识:"extra": {"env": "staging"} - 写一个
scripts命令,比如"post-install-cmd": ["MyScript::loadEnvDeps"] - 在
MyScript类中读取$composer->getPackage()->getExtra()['env'],再调用$installer->install($package)动态安装对应平台包(注意:这属于高级用法,需手动处理 autoload 和 lock 更新) - 更稳妥的做法是:用 Makefile 或 shell 脚本在 CI 中生成不同环境的
composer.json快照,然后cp composer.$ENV.json composer.json && composer install
插件开发本身不受影响,但别让它干合并的活
Composer 插件机制依然健壮,可用于日志上报、自动文档生成、安全扫描等正交功能。但请记住:
- 插件不能修改
composer.json的解析结果,也不能干预依赖图生成过程 - 所有对依赖的“动态干预”都应在
pre-dependencies-solving事件之后失效,因为此时解析器已固化图结构 - 如果你看到某个插件号称“支持条件依赖”,它大概率是在
post-autoload-dump阶段写入额外 autoloader 映射,而非真正改变 require 行为
真正棘手的地方在于:很多团队把 composer-merge-plugin 当作“模块化”的捷径,结果越走越深,直到某次升级 Composer 或 PHP 就全线崩坏。现在删掉它,比半年后花三天 debug 锁文件不一致要省力得多。











