事件机制包含三个角色。
事件Event
定义一个类,一般需要存储一些源数据,因此事件对象应该采用短生命周期的写法,即使用 new UserRegisterd($userId) 的写法。
调度器Dispatcher
触发事件,一般需要传递源数据到事件对象里,并且使该事件的所有监听者去做相应的处理。
监听器Listenner
调度器会将事件对象传递到监听器,监听器得到事件并做相应的处理。由于对象的传递是引用传递,且监听器是串行执行的,所以在监听器里面可以改变事件对象的数据,以传递到下一个监听器继续处理,一个事件可以被多个监听器监听,一个监听器可以监听多个事件,可以设置监听器的执行先后顺序。
定义两个事件
app/Event/UserPayedEvent.php
<?php
namespace App\Event;
class UserPayedEvent
{
public $data;
public function __construct($data)
{
$this->data = $data;
}
public function __destruct()
{
echo 'UserPayedEvent destruct'.PHP_EOL;
}
}
app/Event/UserRegisterEvent.php
<?php
namespace App\Event;
class UserRegisterEvent
{
public $data;
public function __construct($data)
{
$this->data = $data;
}
public function __destruct()
{
echo 'UserRegisterEvent destruct'.PHP_EOL;
}
}
定义两个监听器
app/Listener/SendEmailListener.php
<?php
namespace App\Listener;
use App\Event\UserRegisterEvent;
use Hyperf\Event\Contract\ListenerInterface;
class SendEmailListener implements ListenerInterface
{
public function listen(): array
{
return [
UserRegisterEvent::class
];
}
public function process(object $event)
{
echo 'SendEmailListener done' . PHP_EOL;
var_dump($event->data);
}
}
app/Listener/SendSmsListener.php
<?php
namespace App\Listener;
use App\Event\UserPayedEvent;
use App\Event\UserRegisterEvent;
use Hyperf\Event\Contract\ListenerInterface;
use Swoole\Coroutine\System;
class SendSmsListener implements ListenerInterface
{
public function listen(): array
{
return [
UserRegisterEvent::class,
UserPayedEvent::class,
];
}
public function process(object $event)
{
System::sleep(3);
echo 'SendSmsListener done' . PHP_EOL;
var_dump($event->data);
}
}
注册监听器到配置文件
排在前面的监听器先被执行。
config/autoload/listeners.php
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://doc.hyperf.io
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
return [
\App\Listener\SendSmsListener::class,
\App\Listener\SendEmailListener::class,
];
投递事件
app/Controller/IndexController.php
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://doc.hyperf.io
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace App\Controller;
use App\Event\UserPayedEvent;
use App\Event\UserRegisterEvent;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\AutoController;
use Psr\EventDispatcher\EventDispatcherInterface;
/**
* @AutoController()
*/
class IndexController extends AbstractController
{
/**
* @Inject()
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
public function testUserRegister()
{
$userId = $this->request->input('userId', 0);
$this->eventDispatcher->dispatch((new UserRegisterEvent($userId)));
echo 'done'.PHP_EOL;
}
public function testUserPayed()
{
$userId = $this->request->input('userId', 0);
$money = $this->request->input('money', 0);
$this->eventDispatcher->dispatch((new UserPayedEvent(['userId'=>$userId, 'money'=>$money])));
}
}
多个监听器是串行的,且是有顺序的。
事件对象被最后一个监听器执行完就会被释放掉。