events - ZF3 - 附加到 EventManager 的事件未触发

标签 events zend-framework event-handling zend-framework3

我有一个 EntityRepository 类,我想将一个事件附加到它的“保存”方法。这是 AbstractRepository 类,我在其中设置事件管理器的标识符:

abstract class AbstractRepository extends EntityRepository implements RepositoryInterface
{
    /**
     * @var EventManagerInterface
     */
    protected $events;

    /**
     * Set the event manager instance used by this context.
     *
     * @param EventManagerInterface $events
     *
     * @return mixed
     */
    public function setEventManager(EventManagerInterface $events)
    {
        $events->setIdentifiers([
            __CLASS__,
            get_class($this),
        ]);

        $this->events = $events;

        return $this;
    }

    /**
     * Retrieve the event manager.
     *
     * Lazy-loads an EventManager instance if none registered.
     *
     * @return EventManagerInterface
     */
    public function getEventManager()
    {
        if (!$this->events) {
            $this->setEventManager(new EventManager());
        }

        return $this->events;
    }
}

以及名为 DocumentRepository 的存储库类:

class DocumentsRepository extends AbstractRepository
{
    public function save(Documents $entity)
    {
        $this->getEventManager()->trigger(RepositoryInterface::EVENT_BEFORE_SAVE);

        $this->getEntityManager()->persist($entity);
        $this->getEntityManager()->flush($entity);

        $this->getEventManager()->trigger(RepositoryInterface::EVENT_AFTER_SAVE);

        return $entity;
    }
}

还有一个定义事件名称的接口(interface):

interface RepositoryInterface extends EventManagerAwareInterface
{
    const EVENT_BEFORE_SAVE   = 'before.save';
    const EVENT_AFTER_SAVE    = 'after.save';
}

为了注册监听器,我将以下代码添加到 module.php 中。

public function onBootstrap(MvcEvent $event)
{
    $application    = $event->getApplication();
    $eventManager   = $application->getEventManager();

    /* Register event listener(s) */
    (new DocumentsRepositoryListener($serviceManager))->attach($eventManager);
}

最后,添加监听器类:

class DocumentsRepositoryListener extends AbstractListener implements ListenerAggregateInterface
{
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $sharedEvents = $events->getSharedManager();

        $this->listeners[] = $sharedEvents
            ->attach(DocumentsRepository::class, RepositoryInterface::EVENT_BEFORE_SAVE, [$this, 'beforeSave']);
        $this->listeners[] = $sharedEvents
            ->attach(DocumentsRepository::class, RepositoryInterface::EVENT_AFTER_SAVE, [$this, 'afterSave']);
    }

    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($events->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }

    public function beforeSave(EventInterface $event)
    {
        /* Something to do before saving */
    }

    public function afterSave(EventInterface $event)
    {
        /* Something to do after saving */
    }
}

AbstractListener 类还包含一个构造函数来注入(inject) serviceLocator 和 setter/getter 方法。

现在,我不知道为什么触发器不起作用。还有什么可以忽略的吗!

最佳答案

您编写的用于触发 DocumentsRepository 中的事件的代码没有问题。然而,您对事件管理器的使用存在误解;特别是如何附加事件监听器。

首先要指出的是,您已将存储库类指定为 EventManager自己实例; this 是您应该将事件监听器附加到的实例。 Module::onBootstrap() 中的代码正在向 application 事件管理器注册,这是错误的实例。应用程序事件管理器处理应用程序事件,因此它永远不会触发您的自定义事件。

/* Register event listener(s) */
(new DocumentsRepositoryListener($serviceManager))->attach($eventManager);

将替换为:

$documentRepositoryListener->attach($repository->getEventManager());

注册监听器的逻辑可能更适合在RepositoryFactory中,例如:

class RepositoryFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {       
        $repository = new Repository();

        if ($repository instanceof EventManagerAwareInterface) {
            $eventManager = $repository->getEventManager();
            $listener = $container->get('Foo/Event/Listener');

            $listener->attach($eventManager);
        }

        return $repository;
    }
}

最后,您还需要删除 DocumentsRepositoryListener::attach() 中的 $sharedEvents 用法;因为您想要将事件监听器附加到存储库事件管理器,这将是 $events 参数。

关于events - ZF3 - 附加到 EventManager 的事件未触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56191769/

相关文章:

c# - 我可以通过 DataTrigger (XAML) 调用函数吗?

php - 触发 Laravel 事件

c# - 如何异步调用事件?

php - headMeta -appendName 或appendHttpEquiv

php - Zend update() 更改 id,尽管 id 设置为 NULL 和 auto_increment

javascript - 使用 js 单击事件处理程序设置 CSS 属性

c# - 如何从PropertyChanged事件获取Type?

具有重载的 C# 自定义事件

PHP 使用 Zend_Form 以字节数组形式接收文件

c# - 在 C# 中将参数传递给 DownloadStringCompletedEventHandler