ZF2 отключает прослушиватель от EventManager

Внедрив новое приложение ZF2, я обнаружил, что борюсь с EventManager. В модуле приложения я создал AuthenticationListener и NotifierListener . Первая проверяет правильность аутентификации пользователей, а вторая отображает пользовательские сообщения, адресованные зарегистрированному пользователю.

Теперь я создаю новый модуль, который отправляет xml-файлы для экспорта. Я хочу сохранить AuthenticationListener но отсоединить NotifierListener чтобы избежать ошибок E_NOTIFY . Проблема в том, что после чтения блогов / исходного кода / документации (довольно бедных) и вытягивания волос я не могу понять, как отсоединить слушателя, упомянутого выше.

Приложение module.php

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

Новый модуль.php

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

Ответ заключается в том, чтобы сделать слушателем услугу

Поскольку он не требует никаких параметров конструктора, он invokable, поэтому установите его в массив invokables

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

Извлеките его из диспетчера служб вместо создания нового экземпляра непосредственно в вашем бутстрапе

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

В любом месте, где вы хотите отделить его, вам просто нужно иметь доступ к ServiceManager

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

Вы на правильном пути. Единственное, что вам нужно сделать, это называть detach() на NotifyListener а не на EvenManager . Пример ниже приведен в руководстве Zend Framework для EventManager .

ссылка: http://framework.zend.com/manual/2.0/ru/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 } } не 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 } } 

В этом примере очень хорошо показано, как подготовить слушателя (например, AuthenticationListener ), реализующего ListenerAggregateInterface .

Предполагая ту же ситуацию, что и с вашим объектом Module :

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

Итак, если ваш NotifyListener реализует ListenerAggregateInterface или просто имеет метод detach() вы можете написать свой onBootstrap() чтобы отсоединить слушателя следующим образом:

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

Надеюсь, что это поможет, отзывы будут оценены 🙂

Стоян