Events, the EventManager and ListenerAggregates in Zend Framework 2

There are a bunch of good articles on this subject on the web already, but for my own reference I put together this article listing the steps to take to set up your own custom event listeners in your ZF2 application.

Start by creating a class handling the events. This class will implement the Zend\EventManager\ListenerAggregateInterface. In this example I will create a listener aggregate that takes care of sending out e-mails for different events.

I like to keep my listener aggregates to be groupings of related actions in response to events. For example I would have a LogEventsListener listening to the ‘runtime_error’ event. The handler for this event would for instance make a log entry of what went wrong. At the same time I would have a MailEventsListener also listening to the ‘runtime_error’ event and send out an e-mail to the developer or administrator when a fatal error occurs in the application (random example). Besides the ‘runtime_error’ event there could be other events that either the LogEventsListener or MailEventsListener deal with.

In this case I set the identifier to ‘*’ which means that the listener gets notified about every ‘runtime_error’ event, no matter who triggers the event.
When you want to be more specific and you know for instance that only a specific service triggers a certain event then just set it to that identifier, i.e.:

However as it turns out Zend Framework 2 has a nice undocumented feature, which takes care of attaching listeners that you list in the ‘listeners’ key of the application’s config. I found out about this because I happened to use the same key name ‘listeners’ to register my listeners. 🙂

So we can (and should) leave out the extra bootstrap code and just let the framework take care of registering the listeners. Just add this to any autoloaded config file. I personally use application.config.php for this, because I consider it to be an application setting.
application.config.php:

To be able to trigger events the triggering class has to implement the Zend\EventManager\EventManagerAwareInterface. This makes sure the EventManager gets injected when a new instance of your class is being created. The easiest way is to use the Zend\EventMaanager\EventManagerAwareTrait, which implements the methods required by the interface:

Update (23/07/2014)

After a tip I received I decided to change the listener aggregate classes to implement the SharedListenerAggregateInterface interface instead. This means the aggregate receives the shared eventmanager and thus you don’t have to call $events->getSharedManager() anymore. It requires some small changes to the aggregate class:

Problem is when I try to have the listeners attached automatically through the ‘listeners’ config key, as described in the original blog post above. I’m receiving an exception when I use that so instead I re-added my own custom code in onBootstrap of my application’s main module. I use a different key for this too: ‘aggregate_listeners’ and moved them to module.config.php of the application’s main module.