Appearance
插件机制
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,
],
];
}
}✅ 最佳实践
- 命名空间隔离: 使用
Plugin\{Name}命名空间 - 配置键唯一: 避免与主应用配置键冲突
- 依赖声明: 在 composer.json 中明确依赖
- 版本兼容: 注意与 Hyperf 版本兼容
⚠️ 注意事项
- 加载顺序: 插件配置后加载,可能覆盖主配置
- 循环依赖: 避免插件间循环依赖
- 性能影响: ConfigProvider 中避免耗时操作