fiberphp/event

FiberPHP event dispatcher: supports exact name and prefix wildcard listeners, emit/dispatch dual mode.

Maintainers

Package info

gitee.com/FiberPHP/event

Issues

pkg:composer/fiberphp/event

Transparency log

Statistics

Installs: 3

Dependents: 1

Suggesters: 0

dev-master 2026-08-22 10:23 UTC

This package is auto-updated.

Last update: 2026-08-22 10:24:04 UTC


README

FiberPHP 框架的事件子包。提供轻量级事件分发器,支持精确事件名匹配与通配符前缀匹配,emit(异常安全)与 dispatch(异常传播)双模式触发,通过 config/event.php 声明式注册监听器,由 EventProvider 在 Worker 启动时统一加载。

特性

  • 精确匹配Event::on('user.login', $cb) 注册,Event::emit('user.login', $data) 触发。
  • 通配符前缀Event::on('user.*', $cb) 匹配所有以 user. 开头的事件。
  • 双模式触发emit 捕获异常并记录日志、不中断后续监听器;dispatch 直接抛出异常。
  • halt 模式:首个非 null 响应后停止,支持事件链短路。
  • false 中断:监听器返回 false 时中断后续监听器执行。
  • 声明式注册config/event.php 配置监听器,支持闭包、类方法、多监听器优先级排序。
  • 容器解析['ClassName', 'method'] 格式的监听器自动通过容器解析实例。
  • CLI 诊断event:list 命令列出全部已注册的监听器。

环境要求

  • PHP >= 8.3
  • fiberphp/framework dev-master
  • fiberphp/log dev-master(可选,未安装时回退 framework 兜底 Logger)

安装

composer require fiberphp/event

安装后 PackageInstaller::discover 会自动把 config/event.php 拷贝到应用 config/event.php(幂等,已存在不覆盖),并通过 PackageManifest 注册 EventProvider,无需手动配置。

配置

config/event.php

return [
    // 是否启用事件监听器注册
    'enable' => true,

    // 事件监听器配置
    // key 为事件名,value 为监听器(支持单个或多个)
    // 监听器格式:
    //   - 闭包: fn($data, $event) => ...
    //   - 类方法: [ClassName::class, 'method']  (类通过容器解析)
    //   - 多个监听器: ['key1' => listener, 'key2' => listener, ...]  (按 key 自然排序执行)
    //
    // 通配符前缀:以 "*" 结尾的事件名匹配前缀,如 'user.*' 匹配 'user.login'、'user.logout' 等

    'user.registered' => [
        [\App\Listener\EmailListener::class, 'onUserRegistered'],
        [\App\Listener\SmsListener::class, 'onUserRegistered'],
    ],
    'user.*' => fn($data, $event) => logger()->info("用户事件: {$event}", $data),
    'order.paid' => [\App\Listener\OrderListener::class, 'onOrderPaid'],
];

监听器格式说明:

格式示例说明
闭包fn($data, $event) => ...直接可调用的闭包
类方法[ClassName::class, 'method']类通过容器解析为单例,调用 method
多监听器['a' => $cb1, 'b' => $cb2]数字键按 ksort 自然排序依次执行

使用

基本调用

// framework 全局 helper(推荐)
event();  // 返回 Event 管理器实例

// 注册监听器
Event::on('user.login', function ($data, $event) {
    logger()->info("用户登录: {$event}", $data);
});

// 触发事件
Event::emit('user.login', ['user_id' => 123]);

// 派发事件(异常直接抛出)
Event::dispatch('order.paid', ['order_id' => 456]);

通配符前缀

// 匹配所有 user.* 事件
Event::on('user.*', function ($data, $event) {
    logger()->info("用户事件: {$event}", $data);
});

Event::emit('user.login', $data);    // 触发
Event::emit('user.logout', $data);   // 触发
Event::emit('order.create', $data);  // 不触发

halt 模式

// 首个非 null 响应后停止
$result = Event::emit('cache.get', $key, halt: true);
if ($result !== null) {
    return $result;  // 命中缓存
}

false 中断

// 返回 false 中断后续监听器
Event::on('auth.check', fn() => false);      // 中断
Event::on('auth.check', fn() => true);       // 不会执行

移除监听器

// on() 返回监听器 ID,用于精确移除
$id = Event::on('user.login', $cb);
Event::off('user.login', $id);    // 精确事件移除
Event::off('user.*', $id);         // 通配符移除

查询监听器

// 是否存在监听器
Event::hasListener('user.login');       // true
Event::hasListener('user.logout');      // 通配符 user.* 也会命中

// 获取全部监听器(含前缀匹配)
$listeners = Event::getListeners('user.login');

// 列出全部已注册的监听器(返回 [id => [event_name, callable], ...])
foreach (Event::list() as $id => [$eventName, $callback]) {
    // ...
}

emit vs dispatch

emitdispatch
异常处理捕获并记录日志,继续执行后续监听器直接抛出,中断后续监听器
适用场景通知型事件(日志、缓存、统计)约束型事件(权限、事务、验证)
返回值全部响应数组(halt 模式除外)全部响应数组(halt 模式除外)

CLI 诊断

php start.php event:list

输出表格列出所有已注册的事件监听器(ID、事件名、回调类型)。

License

MIT