Alana Storm
Alana Storm

Reputation: 166046

Using the Symfony 2 Event Dispatcher

How, if at all, should a Symfony 2 bundle developer use the event dispatcher(s) that ship with a stock Symfony 2 system?

I've been digging around in the source for Symfony's event dispatcher, and some of what I've seen has me a little confused as to how I, a third party bundle creator, should use the event dispatcher that ships with Symfony.

Specifically, I noticed that a stock Symfony system has two event dispatcher services. The event_dispatcher and the debug.event_dispatcher. Which service the HttpKernel uses is dependent on environment, and driven by the generated dev or prod container file.

//dev kernel instantiation uses `debug.event_dispatcher` service
new \Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel(
            $this->get('debug.event_dispatcher'), 
            $this, 
            $this->get('debug.controller_resolver')
        );

//prod kernel instantiation uses `event_dispatcher` service         
new \Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel(
            $this->get('event_dispatcher'), 
            $this, 
            new \Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver($this, $this->get('controller_name_converter'), $this->get('monolog.logger.request', ContainerInterface::NULL_ON_INVALID_REFERENCE)));

So far this all makes sense — as it's the debug.event_dispatcher that implements functionality in the web profile's event's tab, including the ability to see which listeners were called, and which listeners were not called.

However, I noticed most (if not all) third party bundles use a hard coded event_dispatcher service call. For example, the JMS/JobQueueBundle uses the following

$this->dispatcher = $this->getContainer()->get('event_dispatcher');

Events dispatched like this fire correctly, but the debug.event_dispatcher doesn't know about them, which means the Symfony web profiler will incorrectly list a called listener as uncalled. Additionally, it's not clear how a bundle author could avoid this, as they don't have the advantage of generating a container file and the HTTP Kernel object doesn't expose an accessor for the protected dispatcher object.

So, is this a bug in Symfony?

Or is the event_dispatcher service only intended for Kernel events, meaning all those bundle authors are misusing it?

Or (the most likely candidate), is it something else I'm missing or haven't considered?

Upvotes: 13

Views: 6181

Answers (1)

Alana Storm
Alana Storm

Reputation: 166046

It looks like the scenario I described above doesn't apply to that latest version of Symfony (2.4.1). Specifically, in 2.4.1, the generated app container file

app/cache/dev/appDevDebugProjectContainer.php

contains the following

$this->aliases = array(
    //...
    'event_dispatcher' => 'debug.event_dispatcher',
    //...
);

That is, unlike the Symfony 2.3.6 project I was working on, the event_dispatcher service has been aliased to the debug.event_dispatcher service (when Symfony runs in development mode). This means when other bundles ask for an event_dispatcher service in dev mode, they're really getting a debug.event_dispatcher service. This lets the the debug.event_dispatcher know about all the events, and it can correctly report on which ones were dispatched.

While it's not a concrete answer, it does indicate the Symfony team was/is aware of the issue, which leads me to believe it's their intention for Bundle developers to use the event_dispatch service fro their own events.

Upvotes: 7

Related Questions