hnraytek/flame-module-kernel
Composer 安装命令:
composer require hnraytek/flame-module-kernel
包简介
A declarative, auto-discovering, event-driven module kernel for PHP 8+/一款 php 8+ 的声明式、自动发现、事件驱动的模块内核
README 文档
README
一款 PHP 8+ 的声明式、自动发现、事件驱动的模块内核,专为 ThinkPHP 6/8 框架设计。
✨ 特性
- 声明式编程:使用 PHP 8 属性(Attributes)定义模块元数据,代码即文档
- 自动发现:自动扫描模块目录和 Composer 包,无需手动注册
- 事件驱动:内置完善的事件系统,支持前置/后置事件钩子
- 依赖注入:通过
#[Provides]自动绑定服务到容器 - 路由自动注册:基于属性的路由定义,自动注册到 ThinkPHP 路由系统
- 缓存优化:支持元数据缓存,生产环境高性能运行
- 模块化架构:轻松构建可插拔的模块化应用
📋 要求
- PHP >= 8.1
- ThinkPHP Framework ^6.0 || ^8.0
- topthink/think-helper ^3.0.3
🚀 快速开始
1. 安装
composer require hnraytek/flame-module-kernel
2. 配置
config/flame.php (可选)自定义模块目录和命名空间
<?php return [ 'module_path' => root_path('FlameModule'), 'namespace' => 'FlameModule\\', ];
config/console.php 执行控制台命令
<?php return [ 'commands' => [ 'flame:discover' => \Hnraytek\Flame\Module\Command\FlameDiscover::class, 'flame:install' => \Hnraytek\Flame\Module\Command\FlameInstall::class, 'flame:uninstall' => \Hnraytek\Flame\Module\Command\FlameUninstall::class, 'flame:sync' => \Hnraytek\Flame\Module\Command\FlameSync::class, ], ];
composer.json 用于自动发现和安装模块
{
"scripts": {
"pre-package-uninstall": [
"Hnraytek\\Flame\\Module\\scripts\\ModuleUninstallHandler::preUninstall"
],
"post-autoload-dump": [
"@php think flame:sync"
]
}
}
3. 创建模块
在 FlameModule/User/UserModule.php 中:
<?php namespace FlameModule\User; use Hnraytek\Flame\Module\Attribute\Module; use Hnraytek\Flame\Module\Attribute\Provides; use Hnraytek\Flame\Module\Attribute\Route; use Hnraytek\Flame\Module\Attribute\Listen; use Hnraytek\Flame\Module\Attribute\Event; #[Module( name: 'user', version: '1.0.0', description: '用户管理模块' )] #[Provides(UserServiceInterface::class, UserService::class)] #[Event('user.created', '用户创建事件')] #[Listen('auth.login', 'UserModule@onLogin', priority: 10)] class UserModule { #[Route(path: '/users', methods: ['GET'], name: 'users.index')] public function index() { return json(['users' => []]); } #[Route(path: '/users/:id', methods: ['GET'], name: 'users.show')] public function show(int $id) { return json(['id' => $id]); } #[Route(path: '/users', methods: ['POST'], name: 'users.store')] public function store() { return json(['message' => 'User created']); } public function onLogin($event) { // 处理登录事件 } }
4. 初始化
# 首次使用时发现模块 php think flame:discover # 或者让 Composer 自动处理 composer dump-autoload
完成!模块已自动注册,路由和事件监听器会自动生效。
🎯 核心概念
模块属性 (#[Module])
定义模块的基本信息:
#[Module(
name: 'module-name',
version: '1.0.0',
depends: ['dependency-module'],
description: '模块描述',
migration: 'MigrationClass'
)]
参数说明:
name: 模块名称version: 版本号depends: 依赖的模块列表description: 模块描述migration: 迁移类(可选)
服务提供 (#[Provides])
将接口绑定到具体实现,自动注册到容器:
#[Provides(UserServiceInterface::class, UserService::class)] #[Provides(RepositoryInterface::class, UserRepository::class)] class MyModule { // ... }
事件声明 (#[Event])
声明模块会触发的事件(用于文档和元数据):
#[Event('user.created', '用户创建后触发')] #[Event('user.updated', '用户更新后触发')] class UserModule { // ... }
事件监听 (#[Listen])
监听其他模块或系统事件:
#[Listen('auth.login', 'MyModule@handleLogin', priority: 10)] #[Listen('order.created', 'MyModule@onOrderCreated')] class MyModule { public function handleLogin($event) { // 处理登录事件 } public function onOrderCreated($event) { // 处理订单创建事件 } }
参数说明:
event: 事件名称handler: 处理方法(格式:类名@方法名)priority: 优先级(数字越大越先执行,默认 0)
路由定义 (#[Route])
在方法上定义路由,自动注册到 ThinkPHP:
#[Route(path: '/api/users', methods: ['GET'], name: 'api.users.index')] public function index() { // ... } #[Route( path: '/api/users/:id', methods: ['PUT'], name: 'api.users.update', middleware: ['auth', 'admin'], pattern: ['id' => '\d+'], domain: 'api.example.com' )] public function update(int $id) { // ... }
参数说明:
path: 路由路径methods: HTTP 方法数组(GET, POST, PUT, DELETE 等)name: 路由名称(可选)middleware: 中间件数组(可选)pattern: 路由参数正则约束(可选)domain: 域名限制(可选)
🔧 高级用法
BaseModuleService - 事务与事件模板
继承 BaseModuleService 获得自动事务管理和事件钩子:
<?php namespace FlameModule\User\Service; use Hnraytek\Flame\Module\BaseModuleService; use Hnraytek\Flame\Module\Event\ModuleEvent; class UserService extends BaseModuleService { public function createUser(array $data) { $event = new ModuleEvent($data); return $this->execute( eventName: 'user.create', event: $event, business: function (ModuleEvent $event) { // 核心业务逻辑(在事务中执行) $userData = $event->getData(); $user = UserModel::create($userData); return $user; }, afterInTransaction: false // 后置事件在事务外执行 ); } }
执行流程:
- 触发
before.user.create事件(可通过$event->abort()中止) - 开启事务,执行业务闭包
- 提交事务
- 触发
after.user.create事件(失败不影响主业务)
ModuleEvent - 事件对象
use Hnraytek\Flame\Module\Event\ModuleEvent; // 创建事件 $event = new ModuleEvent([ 'key1' => 'value1', 'key2' => 'value2' ]); // 获取数据 $data = $event->getData(); $value = $event->getData('key1', 'default'); // 设置数据 $event->set('newKey', 'newValue'); // 中止流程(在 before 事件中) $event->abort('权限不足'); // 检查是否中止 if ($event->isAborted()) { echo $event->getAbortReason(); }
自定义路由属性
你可以在路由方法上使用自定义属性,并在中间件中查询:
// 定义自定义属性 #[Attribute(Attribute::TARGET_METHOD)] class Permission { public function __construct( public string $ability ) {} } // 在模块中使用 class AdminModule { #[Route(path: '/admin/users', methods: ['GET'])] #[Permission('user.manage')] public function manageUsers() { // ... } } // 在中间件中查询 $manager = app(\Hnraytek\Flame\Module\ModuleManager::class); $attrs = $manager->getRouteAttributes('/admin/users', 'GET'); if (isset($attrs[Permission::class])) { $permission = new Permission(...$attrs[Permission::class]); // 检查权限... }
ModuleManager API
use Hnraytek\Flame\Module\ModuleManager; $manager = app(ModuleManager::class); // 获取所有模块元数据 $allModules = $manager->getAllModulesMeta(); // 获取指定模块元数据 $moduleMeta = $manager->getModuleMeta(FlameModule\User\UserModule::class); // 获取路由元数据 $routeMeta = $manager->getRouteMetadata('/users', 'GET'); // 获取路由上的自定义属性 $attributes = $manager->getRouteAttributes('/users', 'GET'); // 检查路由是否有某个属性 $hasAttr = $manager->routeHasAttribute('/users', 'GET', Permission::class); // 获取所有路由索引 $allRoutes = $manager->getAllRoutes(); // 刷新缓存 $manager->refreshCache();
🛠️ 命令行工具
可用命令
# 发现并缓存所有模块(扫描模块目录和 Composer 包) php think flame:discover # 安装指定模块 php think flame:install FlameModule\User\UserModule # 卸载指定模块 php think flame:uninstall FlameModule\User\UserModule # 同步所有模块(自动执行安装、升级、卸载) php think flame:sync
命令说明:
flame:discover: 扫描FlameModule目录和 Composer 包,发现所有模块并生成缓存flame:install: 手动安装指定模块类(执行迁移、注册服务等)flame:uninstall: 手动卸载指定模块类(执行反向迁移、清理资源等)flame:sync: 智能同步所有模块状态,自动检测需要安装、升级或卸载的模块
Composer Scripts 集成
在项目的 composer.json 中添加以下 scripts,实现自动化管理:
{
"scripts": {
"pre-package-uninstall": [
"Hnraytek\\Flame\\Module\\scripts\\ModuleUninstallHandler::preUninstall"
],
"post-autoload-dump": [
"@php think flame:sync"
]
}
}
Scripts 说明:
-
pre-package-uninstall: 在 Composer 卸载包之前自动调用模块卸载流程- 自动执行
php think flame:uninstall <package-name> - 确保模块资源被正确清理
- 自动执行
-
post-autoload-dump: 在 Composer 更新 autoload 后自动执行flame:sync: 自动同步所有 Flame 模块状态
使用场景:
# 安装新模块包时,自动同步 composer require vendor/module-package # 卸载模块包时,自动清理 composer remove vendor/module-package # 更新依赖后,自动发现和同步模块 composer update
📦 Composer 包集成
第三方包可以通过 composer.json 声明模块:
{
"name": "vendor/package",
"extra": {
"flame": {
"module": "Vendor\\Package\\PackageModule"
}
}
}
模块类会被自动发现和加载。
💡 最佳实践
1. 模块版本管理
#[Module(
name: 'order',
version: '2.1.0', // 遵循语义化版本
depends: ['user@^1.0', 'payment@>=2.0'] // 依赖版本约束
)]
2. 模块间通信
// 方式 1: 通过事件 $this->emit('order.created', new ModuleEvent(['order_id' => $id])); // 方式 2: 通过服务容器 $orderService = app(OrderServiceInterface::class); // 方式 3: 直接调用(不推荐,耦合度高)
3. 错误处理
public function createUser(array $data) { try { return $this->execute( eventName: 'user.create', event: new ModuleEvent($data), business: function (ModuleEvent $event) { // 业务逻辑 } ); } catch (\Exception $e) { // 记录日志、返回错误等 Log::error('User creation failed: ' . $e->getMessage()); throw $e; } }
5. 测试模块
// tests/ModuleTest.php use Hnraytek\Flame\Module\ModuleManager; class ModuleTest extends TestCase { public function testModuleDiscovery() { $manager = app(ModuleManager::class); $modules = $manager->getAllModulesMeta(); $this->assertArrayHasKey('user', $modules); $this->assertEquals('1.0.0', $modules['user']['version']); } public function testRouteRegistration() { $manager = app(ModuleManager::class); $route = $manager->getRouteMetadata('/users', 'GET'); $this->assertNotNull($route); $this->assertEquals('users.index', $route['name']); } }
🎨 完整示例
<?php namespace FlameModule\Order; use Hnraytek\Flame\Module\Attribute\Module; use Hnraytek\Flame\Module\Attribute\Provides; use Hnraytek\Flame\Module\Attribute\Route; use Hnraytek\Flame\Module\Attribute\Listen; use Hnraytek\Flame\Module\BaseModuleService; use Hnraytek\Flame\Module\Event\ModuleEvent; #[Module( name: 'order', version: '2.0.0', depends: ['user'], description: '订单管理模块' )] #[Provides(OrderServiceInterface::class, OrderService::class)] #[Listen('payment.completed', 'OrderModule@onPaymentCompleted')] class OrderModule { #[Route(path: '/orders', methods: ['GET'], name: 'orders.index')] public function index() { return json(['orders' => []]); } #[Route(path: '/orders', methods: ['POST'], name: 'orders.create')] public function create() { $service = app(OrderService::class); return json($service->createOrder(request()->post())); } public function onPaymentCompleted(ModuleEvent $event) { // 处理支付完成事件 $orderId = $event->getData('order_id'); // 更新订单状态... } } class OrderService extends BaseModuleService { public function createOrder(array $data) { $event = new ModuleEvent($data); return $this->execute( eventName: 'order.create', event: $event, business: function (ModuleEvent $event) { $orderData = $event->getData(); $order = OrderModel::create($orderData); // 触发订单创建事件 $this->emit('order.created', new ModuleEvent([ 'order_id' => $order->id ])); return $order; } ); } }
运行此示例:
# 1. 创建模块文件后 # 2. 刷新缓存 php think flame:discover # 3. 或使用自动同步 composer dump-autoload # 4. 访问路由 curl http://your-domain/orders
❓ 常见问题
Q: 模块没有被发现?
A: 检查以下几点:
- 模块类是否在配置的
module_path目录下 - 模块类是否有
#[Module]属性 - 命名空间是否正确(应与
FlameModule\前缀匹配) - 执行
php think flame:discover刷新缓存 - 检查
runtime/flame_modules_cache.php是否生成
Q: 路由无法访问?
A: 确认:
- 模块已被成功发现(查看缓存文件)
- 路由方法是否为
public - HTTP 方法是否匹配
- 中间件配置是否正确
Q: 如何调试模块加载问题?
A:
# 查看详细日志 php think flame:discover -v # 检查缓存内容 cat runtime/flame_modules_cache.php # 查看已注册的模块 php think eval "\print_r(app(\Hnraytek\Flame\Module\ModuleManager::class)->getAllModulesMeta(), true);"
Q: Composer 包模块不工作?
A: 确保包的 composer.json 包含:
{
"extra": {
"flame": {
"module": "Vendor\\Package\\PackageModule"
}
}
}
然后执行 composer dump-autoload。
Q: 如何禁用某个模块?
A: 有三种方式:
- 从
FlameModule目录移除模块文件 - 卸载 Composer 包
- 在模块中添加条件判断(不推荐)
📁 项目结构
your-project/
├── FlameModule/ # 模块目录
│ ├── User/
│ │ └── UserModule.php
│ ├── Order/
│ │ └── OrderModule.php
│ └── Auth/
│ └── AuthModule.php
├── config/
│ ├── flame.php # Flame 模块配置
│ └── console.php # 控制台命令配置
├── composer.json # 包含 scripts 配置
└── vendor/
├── flame_modules_cache.php # 缓存文件(自动生成)
├── installed-modules.php # 已安装模块缓存(自动生成)
└── hnraytek/
└── flame-module-kernel/ # FlameModuleKernel 核心
🧪 测试
composer install --dev ./vendor/bin/phpunit test/
📝 许可证
Apache-2.0 License
👤 作者
- haoshuaioo bbmu@qq.com
🤝 贡献
欢迎提交 Issue 和 Pull Request!
☕️ 支持项目
如果这个项目对你有帮助,请给个 Star ⭐
作为一个个人开发者,维护这个项目投入了大量的深夜时光和咖啡。如果这个项目帮到了您,希望您能请我喝一杯咖啡。
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: Apache-2.0
- 更新时间: 2026-06-15
