Search code examples
phpeventszend-framework2

Zend Framework 2 Event Manager


I am learning about zf2 events and below is my code:

module.php

 public function init(ModuleManagerInterface $managers) {       
    $eventManager = $managers->getEventManager();
    /* $eventManager->attach('do', array($this, function ($e) {
        $event = $e->getName();
        $params = $e->getParams();
        printf(
                'Handled event "%s", with parameters %s',
                $event,
                json_encode($params)
                );
        })
    ); */

    $eventManager->attach('do', array($this, 'demoEvent') );

}
public function demoEvent(Event $e) {
    echo  ' in demo Event';
}

and in controller function i have triggered the event.

 $this->getEventManager()->trigger('do', $this, ['aman', 'deep']);

but call to demoEvent action is never made. Even i tried using closure as you can see above but it gives me "Invalid callback provided" Exception.

What i am doing wrong. Can someone help me in understanding Event Manager better. Thanks


Solution

  • Your approach is almost correct. The problem is that you are attaching the event listener "demoEvent" to the application event manager, rather than the controller's event manager.

    As the controller, assuming that it extends AbstractActionController, will also be capable of triggering it's own events.

    You therefore need to update the way you attach the listener to ensure it is registered with the correct event manager.

    There are a few options.

    • Attach event listeners inside the controller factory. You can call $controller->getEventManager()->attach(); inside the factory so when the controller is created the event listener is always attached.

    • Override the attachDefaultListeners() defined in the AbstractActionController this will automatically be called when the controller is initialized by the controller manager. This provides access to the controllers event manager, just be sure to remember to call parent::attachDefaultListeners().

    • Lastly, you can use the "Shared Event Manager" which is really just a proxy to the target event manager (and despite its name, not an event manager). This allows you to only slightly modify the code you have written and keep event listener registration independent of the triggering context (controller).

    For example.

    class Module
    {
    
        public function onBootstrap(MvcEvent $mvcEvent)
        {
            $sharedManager = $mvcEvent->getEventManager()->getSharedManager();
    
            $sharedManager->attach(
                'Foo\\Controller\\BarController', // Event manager 'identifier', which one we want
                'do'                    // Name of event to listen to
                [$this, 'demoEvent'],   // The event listener to trigger
                1,                      // event priority 
            );
        }
    
        public function demoEvent($event)
        {
    
        }
    
    }