Reputation: 1520
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.
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');
}
Upvotes: 1
Views: 1610
Reputation: 11447
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);
Upvotes: 3
Reputation: 5539
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
Upvotes: 0