Внедрив новое приложение ZF2, я обнаружил, что борюсь с EventManager. В модуле приложения я создал AuthenticationListener
и NotifierListener
. Первая проверяет правильность аутентификации пользователей, а вторая отображает пользовательские сообщения, адресованные зарегистрированному пользователю.
Теперь я создаю новый модуль, который отправляет xml-файлы для экспорта. Я хочу сохранить AuthenticationListener
но отсоединить NotifierListener
чтобы избежать ошибок E_NOTIFY
. Проблема в том, что после чтения блогов / исходного кода / документации (довольно бедных) и вытягивания волос я не могу понять, как отсоединить слушателя, упомянутого выше.
public function onBootstrap($e) { $eventManager = $e->getApplication()->getEventManager(); $authListener = new AuthenticationListener(); $authListener->attach($eventManager); $notifyListener = new NotifyListener(); $notifyListener->attach($eventManager); }
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); }
Надеюсь, что это поможет, отзывы будут оценены 🙂
Стоян