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


Reply via email to