我正在使用Symfony的EventDispatcher组件来触发和处理应用程序中的事件,我已经在Helpers.php文件中创建了一个全局帮助程序功能fire(Event $event)
,我可以使用composer自动加载该功能。
Helpers.php
<?php
use App\Http\Helpers\ConfigManager;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
//listeners array defined in another file.
$listeners = [
[\App\Events\ExampleEvent::class => \App\Listeners\ExampleListener::class],
[\App\Events\JobEvent::class => \App\Listeners\JobEventListener::class]
];
if (!function_exists('fire')) {
function fire(Event $event) {
$dispatcher = new EventDispatcher();
$listeners = ConfigManager::getInstance()->getEventListeners();
foreach ($listeners as $listener) {
foreach ($listener as $ev => $handler) {
$instance = new $handler;
if (method_exists($instance, 'handle')) {
$dispatcher->addListener($ev, [$instance, 'handle']);
}
}
}
//events should be dispatched once
//remove duplicate events name from events array.
$events = array_unique(
array_map(function ($listener) {
return array_keys($listener)[0];
}, $listeners)
);
foreach ($events as $ev) {
if ($event instanceof $ev) {
$dispatcher->dispatch($ev, $event);
}
}
}
}
我这样使用它:fire(new ExampleEvent('payload'));
此函数在我的应用程序中随处可见,每次调用它时,都会注册$ listeners数组中的EventListeners,然后调度$ event。
问题是,我不确定这是否是注册和调度事件的最佳方法,因为对于此函数的每次调用,侦听器都必须在调度事件之前进行注册。
我应该在其他地方注册侦听器,然后在函数内部触发事件,有什么想法吗?
PS。我没有使用任何框架。
答案 0 :(得分:0)
我无法引导应用程序,所以我要做的就是创建一个EventManager
和registerListeners()
两个方法的单例fire(Event $event)
,然后我创建了bootstrap.php(工作左右),每个模块我需要一次。
在我的bootstrap.php中:
EventManager::getInstance()->registerListeners();
EventManager单例:
<?php
namespace App\Http\Helpers;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
class EventManager
{
private $dispatcher = null;
private $listeners = null;
protected function __construct()
{
$this->dispatcher = new EventDispatcher();
$this->listeners = ConfigManager::getInstance()->getEventListeners();
}
private function __clone() {} //nah, no clones.
public static function getInstance()
{
static $instance = null;
if ($instance === null) {
$instance = new EventManager();
}
return $instance;
}
public function registerListeners()
{
foreach ($this->listeners as $listener) {
foreach ($listener as $ev => $handler) {
$instance = new $handler;
if (method_exists($instance, 'handle')) {
$this->dispatcher->addListener($ev, [$instance, 'handle']);
}
}
}
}
public function fire(Event $event)
{
//events should be dispatched once, remove duplicate event name from events array.
$events = array_unique(array_map(function ($listener) { return array_keys($listener)[0]; }, $this->listeners));
foreach ($events as $ev) {
if ($event instanceof $ev) {
$this->dispatcher->dispatch($ev, $event);
}
}
}
}
辅助函数fire(Event $event)
如下所示:
<?php
use App\Http\Helpers\EventManager;
use Symfony\Component\EventDispatcher\Event;
if (!function_exists('fire')) {
function fire(Event $event) {
EventManager::getInstance()->fire($event);
}
}
感谢@Cerad的单挑。