This is a very useful post. Is the application flow map that Evan Coury created as a Google Doc going to get updated and folded into the documentation?
I found that very useful, but it fell out of date in the beta rounds. It would be a great addition to the docs, because it's very hard to know what events will fire when without it. Jeremiah On May 13, 2013, at 4:40 AM, Matthew Weier O'Phinney wrote: > On Mon, May 13, 2013 at 12:20 AM, David Muir <davidkm...@gmail.com> wrote: >> On 10/05/13 23:11, Michael Gooden wrote: >>> It should not be firing twice, however you are trying to use the shared >>> event manager the wrong way. >>> >>> If you want to have a listener fire for EVERY dispatch ever, then just >>> attach to normal event manager on EVENT_DISPATCH in one place. If you attach >>> it in the MyModule it will still fire when you access a controller in the >>> Application module. Is that what you need? >> >> >> It was more as an experiment to see what would happen. I was more confused >> by different tutorials showing listeners being attached to the EventManager >> and the SharedEventManager without explaining why one should be used over >> the other. >> >> As for firing twice, I agree, that shouldn't be happening, but >> Zend\Mvc\Application.php triggers MvcEvent::EVENT_DISPATCH on line 309 and >> Zend\Mvc\Controller\AbstractController triggers it on line 115. >> In my opinion this is a bug, and those should be two separate events, but >> there's probably not much that can be done about it now without breaking BC. > > They *ARE* two separate events, that simply happen to be named the same. > > What do I mean? > > Each object composes its own EventManager instance. This is not > shared, and the fact that the instance is not shared is purposeful: > it's to allow each object to trigger isolated events, as well as to > prevent naming collisions. This latter is important -- you can have > the same event name in multiple objects, but they will not trigger the > same listeners due to the fact that the EM instances are separate. > > If you want a listener to trigger for the same event name on different > objects, you have two choices: > > - attach to each object's EM instance separately > - attach to the SharedEventManager, specifying identifiers for each object > > The SharedEventManager is a shared container passed to all EM > instances that were originally pulled from the ServiceManager. This > object allows listeners to attach to events on objects with specific > identifiers; when an event is triggered, the event manager will query > the SharedEventManager to see if it has any listeners on identifiers > it is interested in that correspond to the current event; if so, it > will trigger those, too. > > This explains your original question: > >> Can someone explain why the shared event listener attached via the >> Application module never gets called? > > When you attached to the SharedEventManager, you were attaching the > the identifier "Application", which will only get triggered by an > object that has the identifier "Application" -- most likely, this will > be a controller, as the default controller implementations will add > their top-level namespace as an event identifier. > (Zend\Mvc\Application does not itself define that identifier, but > instead the identifier "Zend\Mvc\Application".) > > You also ask the following: > >> Secondary to this, I've seen some examples attach listeners to the shared >> manager, and others attach them to the event manager. When do I use one >> instead of the other? > > The general rule of thumb is: > > - If you already have direct access to an object, and want to attach > listeners to it, use its composed EventManager directly. > - If you do not already have direct access to an object, or do not > know if it will even come into scope in the current request, use the > SharedEventManager to attach listeners. > > So, as concrete examples: Let's say I want to attach an event to > trigger when routing has finished. I will generally do this during the > bootstrap event from within my module. Inside a bootstrap listener, I > can access the Application instance directly via either > $e->getTarget() or $e->getApplication(). Since the route event is > triggered directly by the Application instance, I can attach directly > to its EM instance: > > $application = $e->getTarget(); > $events = $application->getEventManager(); > $events->attach('route', $callback, -10); > > Now let's say I want to attach a listener to an event triggered by a > domain model. I don't know yet if that model will be used in this > request, much less if the controller that will communicate with it > will be selected. As such, I'll use the SharedEventManager, which I > will pull from the EM instance composed in the Application instance. > > $application = $e->getTarget(); > $events = $application->getEventManager(); > $sharedEvents = $events->getSharedManager(); > $sharedEvents->attach('My\Domain\Model', 'fetch', $callback); > > Hopefully that answers the questions you have! > >> >> Cheers, >> David >> >>> >>> Cheers, >>> >>> Michael >>> >>> >>> >>> On 10 May 2013 15:01, David Muir <davidkm...@gmail.com >>> <mailto:davidkm...@gmail.com>> wrote: >>> >>> Michael, >>> >>> Thanks for the explanation. It does explain the issue I have having. >>> >>> So the gist is: >>> >>>> $sharedEvents->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH >>>> >>> >>> means that this even will only be triggered if the context is that >>> namespace. So the one in Application will fire if the context is >>> "Application" and the one in MyModule will fire if the context is >>> "MyModule". >>> >>> So as an experiment, in Application I tried attaching a listener >>> to 'MyModule' instead of __NAMESPACE__ and it work as expected. It >>> only fires when hitting a controller in MyModule. >>> >>> But what if I want to attach something that is triggered in all >>> contexts on the dispatch event? I tried using the * wildcard, but >>> now the shared listeners get hit twice: >>> >>> shared event listener from application module called >>> shared event listener from my module called >>> event listener from application module called >>> event listener from my module called >>> shared event listener from application module called >>> shared event listener from my module called >>> >>> If my understanding is correct, this happens because there are two >>> EventManager involved. First is the Application's EventManager, >>> which first triggers the shared events, then triggers the local >>> events. Then the controller itself triggers >>> MvcEvent::EVENT_DISPATCH on its own EventManager instance when the >>> controller's dispatch() method gets called. This in turn triggers >>> the shared events a 2nd time. >>> >>> I guess I got exactly what I asked for, but wasn't >>> expecting MvcEvent::EVENT_DISPATCH to be triggered twice. Kind of >>> feels wrong... >>> >>> Cheers, >>> David >>> >>> On 10/05/2013, at 4:46 PM, Michael Gooden >>> <mich...@bluepointweb.com <mailto:mich...@bluepointweb.com>> wrote: >>> >>>> Hi David, >>>> >>>> Keep in mind that you are working with the Zend\Mvc\Application's >>>> EventManager instance. Try and follow the code execution in the >>>> Application::run() function, to see when and why different events >>>> fire. >>>> >>>> I would hazard a guess and say that you are accessing a >>>> controller in the MyModule, and not in the main Application >>>> module. If you run a controller from the Application module, you >>>> will then see the 'shared event from application' message show >>>> instead of from mymodule. The reason this is happening is because >>>> the shared event manager listener you are attaching is listening >>>> for the event identifier of __NAMESPACE__. When the dispatch >>>> event gets called against a controller under MyModule, only the >>>> listener tied to the namespace of that controller will be fired. >>>> The reason you will always see both normal event listener >>>> messages is because those listeners are both attached to the >>>> dispatch event. >>>> >>>> I feel I am failing at explaining this, can you add me on Skype? >>>> >>>> Cheers, >>>> >>>> Michael Gooden >>>> >>>> >>>> On 10 May 2013 03:41, David Muir <davidkm...@gmail.com >>>> <mailto:davidkm...@gmail.com>> wrote: >>>> >>>> I'm getting some weird behaviour with the EventManager and >>>> SharedEventManager when used in the Application module vs >>>> other modules. >>>> >>>> Application Module: >>>> >>>> public function onBootstrap(MvcEvent $e) >>>> { >>>> //$e->getApplication()->getServiceManager()->get('translator'); >>>> $eventManager = >>>> $e->getApplication()->getEventManager(); >>>> $moduleRouteListener = new ModuleRouteListener(); >>>> $moduleRouteListener->attach($eventManager); >>>> >>>> $eventManager->attach(MvcEvent::EVENT_DISPATCH, function >>>> ($event){ >>>> echo 'event listener from application module >>>> called' . PHP_EOL; >>>> }); >>>> >>>> $sharedEvents = $eventManager->getSharedManager(); >>>> >>>> $sharedEvents->attach(__NAMESPACE__, >>>> MvcEvent::EVENT_DISPATCH, function ($event){ >>>> echo 'shared event listener from application >>>> module called'. PHP_EOL; >>>> }); >>>> >>>> } >>>> >>>> >>>> My Module: >>>> >>>> public function onBootstrap(\Zend\EventManager\EventInterface $e) >>>> { >>>> >>>> $eventManager = >>>> $e->getApplication()->getEventManager(); >>>> $sharedEvents = $eventManager-> getSharedManager(); >>>> >>>> $eventManager->attach(MvcEvent::EVENT_DISPATCH, function >>>> ($event){ >>>> echo 'event listener from my module called'.PHP_EOL; >>>> }); >>>> >>>> $sharedEvents->attach(__NAMESPACE__, >>>> MvcEvent::EVENT_DISPATCH, function ($event){ >>>> echo 'shared event listener from my module >>>> called'.PHP_EOL; >>>> }); >>>> >>>> } >>>> >>>> >>>> >>>> outputs: >>>> >>>> shared event listener from my module called >>>> event listener from application module called >>>> event listener from my module called >>>> >>>> >>>> Can someone explain why the shared event listener attached >>>> via the Application module never gets called? >>>> >>>> Secondary to this, I've seen some examples attach listeners >>>> to the shared manager, and others attach them to the event >>>> manager. When do I use one instead of the other? >>>> >>>> Cheers, >>>> David >>>> >>>> >>>> -- >>>> List: fw-general@lists.zend.com >>>> <mailto:fw-general@lists.zend.com> >>>> >>>> Info: http://framework.zend.com/archives >>>> Unsubscribe: fw-general-unsubscr...@lists.zend.com >>>> <mailto:fw-general-unsubscr...@lists.zend.com> >>>> >>>> >>>> >>> >>> >> > > > > -- > Matthew Weier O'Phinney > Project Lead | matt...@zend.com > Zend Framework | http://framework.zend.com/ > PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc > > -- > List: fw-general@lists.zend.com > Info: http://framework.zend.com/archives > Unsubscribe: fw-general-unsubscr...@lists.zend.com > > -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com