ZF2 detach listener from EventManager

匿名 (未验证) 提交于 2019-12-03 08:30:34

问题:

Implementing a new ZF2 app I found myself struggling with the EventManager. In the application module I created an AuthenticationListener and a NotifierListener. The first checks for proper authentication on users and the second displays custom messages addressed to the logged user.

Now I'm creating a new module that dispatches xml files to export. I want to keep the AuthenticationListener but detach the NotifierListener to avoid E_NOTIFY errors. The problem is that after reading blogs/source code/documentation (pretty poor) and pulling my hair out I'm unable to understand how to detach the listener mentioned above.

Application module.php

public function onBootstrap($e) {     $eventManager = $e->getApplication()->getEventManager();      $authListener = new AuthenticationListener();     $authListener->attach($eventManager);      $notifyListener = new NotifyListener();     $notifyListener->attach($eventManager); } 

New module.php

public function onBootstrap($e) {     $eventManager = $e->getApplication()->getEventManager();      // ... $eventmanager->detach('NotifyListener'); } 

回答1:

The answer is to make your listener a service

Since it requires no constructor params, it's invokable, so set it in the invokables array

public function getServiceConfig() {     return array(         'invokables' => array(             'NotifyListener' => 'FQCN\To\NotifyListener',         ),     ); } 

Fetch it from the service manager instead of creating a new instance directly in your bootstrap

public function onBootstrap($e) {     $eventManager = $e->getApplication()->getEventManager();      $sm = $e->getApplication()->getServiceManager();      $notifyListener = $sm->get('NotifyListener')     $notifyListener->attach($eventManager); } 

Anywhere you want to detach it, you just need to be able to get at the ServiceManager

 // in any ServiceLocator aware class  $sm = $this->getServiceLocator();  $eventManager = $sm->get('Application')->getEventManager();  $notifyListener = $sm->get('NotifyListener');  $notifyListener->detach($eventManager); 


回答2:

You are on the right path. The only thing that you need to do is to call detach() on your NotifyListener and not on the EvenManager. The example bellow comes from the Zend Framework manual for the EventManager.

link: http://framework.zend.com/manual/2.0/en/modules/zend.event-manager.event-manager.html#examples

use Zend\Cache\Cache; use Zend\EventManager\EventCollection; use Zend\EventManager\ListenerAggregateInterface; use Zend\EventManager\EventInterface;  class CacheListener implements ListenerAggregateInterface {     protected $cache;      protected $listeners = array();      public function __construct(Cache $cache)     {         $this->cache = $cache;     }      public function attach(EventCollection $events)     {         $this->listeners[] = $events->attach('get.pre', array($this, 'load'), 100);         $this->listeners[] = $events->attach('get.post', array($this, 'save'), -100);     }      public function detach(EventManagerInterface $events)     {         foreach ($this->listeners as $index => $listener) {             if ($events->detach($listener)) {                 unset($this->listeners[$index]);             }         }     }      public function load(EventInterface $e)     {         // some code to load     }      public function save(EventInterface $e)     {         // some code to save      } } 

This example illustrates very well how to prepare a listener (e.g. AuthenticationListener) implementing ListenerAggregateInterface.

Assuming the same situation as with your Module object:

public function onBootstrap($e) {     $eventManager = $e->getApplication()->getEventManager();     $cacheListener = new CacheListener($cache);     $cacheListener->detach($eventManager); } 

So, assuming your NotifyListener implements ListenerAggregateInterface or simply has a detach() method you can write your onBootstrap() method to detach the listener like this:

public function onBootstrap($e) {     $eventManager = $e->getApplication()->getEventManager();     $notifyListener = new NotifyListener();     $notifyListener->detach($eventManager); } 

Hope this helps, feedback will be appreciated :)

Stoyan



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!