原出处:https://www.ziruchu.com/art/619
事件模型必须基于 PSR-14 规范实现。
事件概念
事件模式是一种经过了充分测试的可靠机制,是一种非常适用于解耦的机制,分别存在以下 3 种角色:
事件(Event) 是传递于应用代码与 监听器(Listener) 之间的通讯对象
监听器(Listener) 是用于监听 事件(Event) 的发生的监听对象
事件调度器(EventDispatcher) 是用于触发 事件(Event) 和管理 监听器(Listener) 与 事件(Event) 之间的关系的管理者对象
举例来说,比如用户注册之后,我们要发送一封邮件给用户。可以使用事件与监听者来实现:
1)定义一个用户注册事件;
2)定义一个监听事件的监听者;
3)事件调度器调度事件(也就是开始使用事件了);
4)事件一旦被触发,监听者就会监听到,从而相应的逻辑处理。
使用事件
方式一:基础使用
第一步:定义一个事件
<?php
// App\Event\UserRegistered.php
namespace App\Event;
// 用户注册事件
use App\Model\User;
class UserRegistered
{
public function __construct(public User $user)
{
}
}
第二步:定义一个监听者
监听器都需要实现一下 Hyperf\Event\Contract\ListenerInterface 接口的约束方法。
<?php
// App\Listener\UserRegisteredListener.php
namespace App\Listener;
use App\Event\UserRegistered;
use Hyperf\Event\Contract\ListenerInterface;
class UserRegisteredListener implements ListenerInterface
{
public function listen(): array
{
// 该监听器需要监听的事件,可以监听多个事件
return [
UserRegistered::class
];
}
public function process(object $event): void
{
// 此处是事件触发后的业务逻辑处理
echo '用户注册事件触发,我执行了, 用户 ID:' . $event->user->id;
}
}
第三步:注册监听器
<?php
// config/autoload/listeners.php
declare(strict_types=1);
return [
\App\Listener\UserRegisteredListener::class,
];
第四步:事件调度器分发事件
此处我在控制器进行事件调度。可以在其他位置进行事件调度,如 UserService 层。
<?php
// App\Controller\Test\UserController.php
use Psr\EventDispatcher\EventDispatcherInterface;
#[Inject]
protected EventDispatcherInterface $dispatcher;
#[GetMapping('/users/store')]
public function store()
{
$user = User::query()->find(1);
// 事件调度
$this->dispatcher->dispatch(new UserRegistered($user));
}
方式二:注解方式使用事件
Hyperf 提供了更为方便的监听器注册方式,使用 #[Listener] 进行注解后,就不需要在配置文件 listeners.php 中注册了。使用方式如下:
<?php
// App\Listener\UserRegisteredListener.php
namespace App\Listener;
use App\Event\UserRegistered;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
// 注册方式注册监听者
#[Listener]
class UserRegisteredListener implements ListenerInterface
{
// 代码省略
}
当使用注解注册监听器时,可以通过设置 priority 属性定义当前监听器的,如 #[Listener(priority=1)],底层使用 SplPriorityQueue 结构储存,priority 数字越大优先级越高。
使用 #[Listener] 注解时需 use Hyperf\Event\Annotation\Listener; 命名空间;
对于事件,理解加实操更容器理解。
测试demo:
<?php
namespace App\Event;
// 用户注册事件
use App\Model\User;
class UserRegistered
{
public function __construct(public User $user)
{
}
}
<?php
// App\Listener\UserRegisteredListener.php
namespace App\Listener;
use App\Event\UserRegistered;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
// 注册方式注册监听者
#[Listener]
class UserRegisteredListener implements ListenerInterface
{
public function listen(): array
{
// 该监听器需要监听的事件,可以监听多个事件
return [
UserRegistered::class
];
}
public function process(object $event): void
{
var_dump($event);
// 此处是事件触发后的业务逻辑处理
echo '用户注册事件触发,我执行了, 用户 ID:' . $event->user->id;
}
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace App\Controller;
use App\Event\UserRegistered;
use App\Model\OrderTest;
use App\Model\User;
use App\Service\UserService;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Psr\EventDispatcher\EventDispatcherInterface;
#[Controller(prefix: "lgbhf/index")]
class IndexController extends AbstractController
{
#[Inject]
protected EventDispatcherInterface $dispatcher;
#[GetMapping('store')]
public function store()
{
$user = User::query()->find(1);
// 事件调度
$this->dispatcher->dispatch(new UserRegistered($user));
}
}
网友评论