应为每个内核配置独立 composer.json 并通过 path 仓库方式在主项目中声明依赖,避免共享 vendor 导致的版本冲突、autoload 覆盖及 CI 不可控等问题。

大型项目用单个 composer.json 管理多个内核(如用户中心、订单服务、支付网关)必然导致依赖冲突、autoload 覆盖、CI 构建不可控——这不是配置问题,是架构层级错误。
为什么不能把所有内核塞进一个 composer.json
共享 vendor/ 目录会让不同内核强制共用同一版 guzzlehttp/guzzle 或 psr/log。你升级支付模块的 HTTP 客户端,用户中心的日志上下文可能就丢失 trace ID;更糟的是,autoload 中的 PSR-4 映射若都写 "App": "src/",最后只有最后一个模块的命名空间生效,类自动加载直接失败。
- CI 每次构建都要
composer install全量依赖,哪怕只改了一个内核的路由逻辑 -
composer.lock变得巨大且难以审查,某次update后无法定位哪个内核拖垮了整个依赖图 - 本地开发时,
user-service依赖symfony/console:^6.4,而order-module锁死在^5.4,Composer 会静默降级或报错退出,不提示具体冲突源
用 path 类型仓库隔离每个内核
每个内核(如 modules/user-service)必须有独立的 composer.json,含唯一 name(如 "myapp/user-service")和精准 autoload 配置(如 "MyApp\UserService": "src/")。主项目根目录的 composer.json 不直接写依赖,而是声明它们为本地路径包:
{
"repositories": [
{ "type": "path", "url": "./modules/user-service" },
{ "type": "path", "url": "./modules/order-module" }
],
"require": {
"myapp/user-service": "*",
"myapp/order-module": "*"
}
}
关键点:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
url必须是相对于根composer.json的路径,不能含../ -
*默认匹配dev-main分支,要固定提交用"dev-main#abc123" - 执行
composer update时,Composer 会软链接各模块到vendor/,而非复制文件——修改模块代码立即生效,无需重复 install
插件化加载内核,而非自动注册
Composer 只负责把内核代码拉下来并生成 autoload,**绝不**让它自动启用任何内核逻辑。真正的加载控制权必须交还给应用层:
- 在主程序启动时,扫描
config/enabled-kernels.php(内容为['user-service', 'order-module']),按需实例化对应内核的入口类 - 每个内核提供统一接口(如
KernelInterface::boot()),主程序调用时传入环境配置,不依赖全局命名空间或静态方法 - 禁止在任何内核的
autoload中触发副作用(如register_shutdown_function或ini_set),这类操作必须收口到主程序的生命周期钩子里
这样,上线时禁用某个内核只需删掉配置项,无需改代码、不重装依赖、不触发 Composer 事件。
避免踩进 composer-merge-plugin 这个坑
别用 composer-merge-plugin 合并多个内核的 composer.json——它已被官方弃用,且在 PHP 8.2+ 下会抛 Deprecated: Creation of dynamic property。更致命的是,它绕过 Composer 原生依赖解析,导致 composer.lock 记录的版本与实际安装结果不一致,CI 环境偶发失败。
真正需要“多内核整合”的地方,应该用 config.platform 锁定目标环境能力(如 {"ext-pcntl": "8.1.27"}),再配合 extra 字段驱动自定义脚本(如 "post-install-cmd": ["MyLoader::scanKernels"])。动态行为永远交给运行时,不是交给依赖管理器。

















