Zend Framework 2 : Register Event Listeners in Configuration File
Zend Framework 2.2 released. It comes with ton of new features. Now, I will show you how to set event listeners in Configuration File. Event Listeners can be registered in config/application.config.php.
For example, I have a sample listener like this :
//module/YourModule/src/YourModule/Event/MySampleListener.php namespace YourModule\Event; use Zend\EventManager\ListenerAggregateInterface; use Zend\EventManager\EventManagerInterface; use Zend\EventManager\EventInterface; class MySampleListener implements ListenerAggregateInterface { protected $listeners = array(); public function attach(EventManagerInterface $events) { $this->listeners[] = $events->attach('eventName', array($this, 'doEvent')); } public function detach(EventManagerInterface $events) { foreach ($this->listeners as $index => $listener) { if ($events->detach($listener)) { unset($this->listeners[$index]); } } } public function doEvent(EventInterface $event) { echo 'param id = '.$event->getParam('id'); } }
Let’s register :
a. in config/application.config.php
return array( 'listeners' => array( 'MySampleListener' ), // This should be an array of module namespaces used in the application. 'modules' => array( 'Application', 'YourModule', //Your module here ), 'module_listener_options' => array( 'module_paths' => array( './module', './vendor', ), 'config_glob_paths' => array( 'config/autoload/{,*.}{global,local}.php', ), ), );
b. register as service at YourModule/config/module.config.php
//module/YourModule/config/module.config.php return array( 'service_manager' => array( 'invokables' => array( 'MySampleListener' => 'YourModule\Event\MySampleListener', ), ), 'controllers' => array( //other config here... ), 'routes' => array( //other config here... ), );
Try calling in Controller :
//module/YourModule/src/YourModule/Controller/IndexController.php namespace YourModule\Controller; use Zend\Mvc\Controller\AbstractActionController; class IndexController extends AbstractActionController { public function indexAction() { $mysampleListener = $this->getServiceLocator()->get('MySampleListener'); $this->getEventManager()->attachAggregate($mysampleListener); $parameter = array('id' => 1); $this->getEventManager()->trigger('eventName', $this, $parameter); } }
Um…, let’s make it separate, attach via Module::onBootstrap :
//module/YourModule/Module.php namespace YourModule; use Zend\Mvc\MvcEvent; class Module { public function onBootstrap(MvcEvent $e) { $eventManager = $e->getApplication()->getEventManager(); $sharedManager = $eventManager->getSharedManager(); $sm = $e->getApplication()->getServiceManager(); $sharedManager->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', function($e) use ($sm) { $controller = $e->getTarget(); $controller->getEventManager()->attachAggregate($sm->get('MySampleListener')); }, 2); } public function getConfig(){/* common code here */} public function getAutoloaderConfig(){ /* common code here */} }
And you just call in controller by :
//module/YourModule/src/YourModule/Controller/IndexController.php namespace YourModule\Controller; use Zend\Mvc\Controller\AbstractActionController; class IndexController extends AbstractActionController { public function indexAction() { $parameter = array('id' => 1); $this->getEventManager()->trigger('eventName', $this, $parameter); } }
I got some question about why need to register at config/application.config.php ? It’s to make it callable during onBootstrap(MvcEvent $e) directly by :
$eventManager->trigger('eventName', $this, array('id' => 1));
at the Module.php.
References :
1. https://github.com/zendframework/zf2/pull/3931
2. http://samminds.com/2013/04/understanding-zf2-configuration/
3. http://framework.zend.com/blog/zend-framework-2-2-0-stable-released.html
Thanks for article! For what listeners are used in practice?
Read :
http://www.michaelgallego.fr/blog/2013/05/12/understanding-the-zend-framework-2-event-manager/
where to create this MySampleListener class ?there is no event folder in MyModule…do i have to create one?please explain
Look at the namespace. Please read the docs on module section.
not clear.i have read modules section of the docs but did not come across something that explains this..can u help me with a link plz..i know that listeners are added in zend/modulemanager/listener..if the namespace is mymoule/event then it must be in that directory..so wanted some clarification..it would be great if u could explain
updated. hopefully help you.
thanks for updating the post and sorry if it caused too much trouble.we turn to blogs for knowledge when we fail to understand the doc.thanks for helping though
Hi, thank you for this good example. I finally got it to work! Thank you again and do keep blogging, I have learned a lot from you.
You’re welcome 😉
Hi, thanks for your great worked example.
One question though, I’m running ZF 2.2.4 and the config array “listeners” doesn’t appear to do anything. As in I have your example working and if I delete that config entry everything still works fine.
Could you shed any more light on what this array is supposed to be doing:
‘listeners’ => array(
‘MySampleListener’
)
Many thanks
Hi abarnesuk, thanks for pointing that, I’ve updated the post, it should be written at config/application.config.php. by writing that, it to make triggered directly at Module.php at onBootstrap function :
Hello i have two questions about your tutorial:
1. What does ‘listeners’ key in module.config.php? I can’t find any official documentation about that.
2. How can i prevent adding a closure in module.php’s onBootstrap method? Is there another way to do same thing instead of defining a closure in module.php?
thanks for pointing that, I’ve updated the post, it should be written at config/application.config.php.
1. by writing that, it to make triggered directly at Module.php at onBootstrap function :
You can contribute to make the docs better 🙂 https://github.com/zendframework/zf2-documentation
2. you can do like this :
Hello samsonasik , Can you help me to resolve a little problem with event ?
I have a chunk of code in my project follow :
======================================================
class Module {
public function onBootstrap(MvcEvent $e) {
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$sharedEvent->attach(‘Test\Controller\IndexController’,[b] MvcEvent::EVENT_RENDER[/b], function($event){
echo ‘render’;
});
}
======================================================
It’s not display “render” . Please help me .
SELECT `myidol` FROM `persons` WHERE `nameperson` = ‘samsonasik’ .
Sorry . Im not good english. im a vietnamese
what do you want to achieve ? I think it should be :
read https://samsonasik.wordpress.com/2013/03/30/zend-framework-2-getting-closer-with-eventmanager/
Sorry , please remove tag BBcode [b]
How can call same event via trigger from a service class (instance of ServiceAwareInterface)
please read https://samsonasik.wordpress.com/2013/03/30/zend-framework-2-getting-closer-with-eventmanager/ and understand that
Thank you for the article. However, I don’t see the benefit of having the MySampleListener service listed in ‘listeners’ config key. Where do you access it? What is it actually good for? I see you retrieving and attaching everything manually anyway and see no usage of the config. I would appreciate your reply. Thank you.
you can directly call the event on onbootstrap, see my last sentences on the post.
Thank you. I used wrong term benefit I’m sorry. I meant what does the key actually do. The answer is that all services In ‘listeners’ key are automatically attached in Application->bootstrap(). So I don’t need to attach them manually in Module->onBootstrap, which I see you do in the example above. So I got confused a little. Thank you though.
We have problem :- ZF3 Event Listener Class when extends it start listening same event multiple time
we have class in ZF3 see below classes when we extend event Listener class. Now when event is triggered, it trigger Event listener multiple time. How to avoid multiple hit to same listener ? We need only trigger event in either base class or Derived Listener as & when loaded for two different modules.
In File: EventListener
————————————————————
class EventListener implements ListenerAggregateInterface
{
protected $listeners = array();
/**
* {@inheritDoc}
*/
public function attach(EventManagerInterface $events)
{
$sharedEvents = $events->getSharedManager();
$this->listeners[] = $sharedEvents->attach([‘TestEventService’], ‘event_change’, array($this, ‘onChangeEvent’));
}
public function detach(EventManagerInterface $events)
{
}
public function onChangeEvent(){
// here some code
}
}
in File: EventListenerExtended
————————————————————————-
class EventListenerExtended extends EventListener
{
public function onChangeEvent(){
//here some code
}
}
in two different modules we have module.php that have triggered:
———————————————————————————-
public function onBootstrap(EventInterface $e)
{
$eventManager->attach(new EventListener());
}
public function onBootstrap(EventInterface $e)
{
$eventManager->attach(new EventListenerExtended());
}
you can register at ‘dispatch’ event, so it can determine when it executed, eg: