Skip to content

插件机制

MineShop 基于 Hyperf 的 ConfigProvider 机制实现插件系统,支持配置自动合并、热插拔等特性。

🎯 工作原理

┌─────────────────────────────────────────────────────────────┐
│                    Composer Autoload                         │
│                         ↓                                    │
├─────────────────────────────────────────────────────────────┤
│                    ConfigProvider                            │
│                         ↓                                    │
├─────────────────────────────────────────────────────────────┤
│                    Config Merge                              │
│                         ↓                                    │
├─────────────────────────────────────────────────────────────┤
│                    Application Boot                          │
└─────────────────────────────────────────────────────────────┘

📦 ConfigProvider 详解

基本结构

php
class ConfigProvider
{
    public function __invoke(): array
    {
        return [
            'annotations' => [...],    // 注解扫描
            'dependencies' => [...],   // 依赖注入
            'commands' => [...],       // 命令行
            'processes' => [...],      // 自定义进程
            'crontab' => [...],        // 定时任务
            'async_queue' => [...],    // 异步队列
            'middlewares' => [...],    // 中间件
        ];
    }
}

配置合并规则

php
// 主应用配置
// config/autoload/async_queue.php
return [
    'default' => [
        'driver' => RedisDriver::class,
        'channel' => '{default-queue}',
    ],
];

// 插件配置
// plugins/export-center/src/ConfigProvider.php
'async_queue' => [
    'export' => [
        'driver' => RedisDriver::class,
        'channel' => '{export-queue}',
    ],
],

// 合并后结果
[
    'default' => [...],  // 主应用配置
    'export' => [...],   // 插件配置(自动合并)
]

🔧 注册机制

1. composer.json 声明

json
{
    "extra": {
        "hyperf": {
            "config": "Plugin\\ExportCenter\\ConfigProvider"
        }
    }
}

2. 自动发现

Hyperf 在启动时自动扫描所有包的 extra.hyperf.config,加载 ConfigProvider。

3. 配置合并

php
// Hyperf 内部实现
foreach ($providers as $provider) {
    $config = (new $provider)();
    $this->mergeConfig($config);
}

📋 支持的配置项

配置项说明合并方式
annotations注解扫描路径追加
dependencies依赖注入绑定覆盖
commands命令行命令追加
processes自定义进程追加
crontab定时任务追加
async_queue异步队列合并
middlewares中间件追加

🎨 实际案例

导出中心插件

php
// plugins/export-center/src/ConfigProvider.php
class ConfigProvider
{
    public function __invoke()
    {
        return [
            // 1. 注解扫描
            'annotations' => [
                'scan' => [
                    'paths' => [__DIR__],
                ],
            ],
            
            // 2. 异步队列(自动合并到主配置)
            'async_queue' => [
                'export' => [
                    'driver' => RedisDriver::class,
                    'channel' => '{export-queue}',
                    'handle_timeout' => 600,
                    'processes' => 1,
                    'concurrent' => ['limit' => 5],
                ],
            ],
            
            // 3. 消费进程
            'processes' => [
                ExportConsumerProcess::class,
            ],
        ];
    }
}

✅ 最佳实践

  1. 命名空间隔离: 使用 Plugin\{Name} 命名空间
  2. 配置键唯一: 避免与主应用配置键冲突
  3. 依赖声明: 在 composer.json 中明确依赖
  4. 版本兼容: 注意与 Hyperf 版本兼容

⚠️ 注意事项

  1. 加载顺序: 插件配置后加载,可能覆盖主配置
  2. 循环依赖: 避免插件间循环依赖
  3. 性能影响: ConfigProvider 中避免耗时操作

📚 相关文档

基于 Apache-2.0 许可发布 | 感谢 MineAdmin 提供的优秀基础框架