New in Symfony 4.4: Simpler Event Listeners
October 23, 2019 • Published by Javier Eguiluz
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
Symfony triggers several events during the request-response flow. Event listeners and event subscribers allow you to execute some code to respond to those events.
Event subscribers are usually preferred because they can listen to multiple events and they don't require any configuration when using autoconfiguration. In Symfony 4.4 we've improved event listeners to make them easier to configure.
First, remove the event
attribute of the kernel.event_listener
tag
used when registering the listener:
1 2 3 4 5 6
# config/services.yaml
services:
App\EventListener\MyRequestListener:
tags:
- - { name: kernel.event_listener, event: kernel.request }
+ - { name: kernel.event_listener }
Then, make sure that your event listener uses a method named after the event
(onKernelRequest()
in this example) or __invoke()
to avoid having to
define the event listener method in the kernel.event_listener
tag:
1 2 3 4 5 6 7 8 9 10 11
namespace App\EventListener;
use Symfony\Component\HttpKernel\Event\RequestEvent;
final class MyRequestListener
{
public function __invoke(RequestEvent $event): void
{
// ...
}
}
That's all. Symfony will now introspect the arguments of the listener method
(RequestEvent
in this example) to know which event is the event listener
associated to.
Thanks to this simplified configuration, you can remove the configuration of all your event listeners and replace it by the following, which will register all event listeners at once:
1 2 3 4 5
# config/services.yaml
services:
App\EventListener\:
resource: ../src/EventListener/*
tags: [kernel.event_listener]
Invokable Doctrine Entity Listeners
Doctrine entity listeners are one of the several ways to work with
Doctrine events. In Symfony 4.4 we've also improved them to allow using the
__invoke()
magic PHP method to define the logic of the listener:
1 2 3 4 5 6 7 8 9 10 11 12
namespace App\EventListener;
use App\Entity\User;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
class UserChangedNotifier
{
public function __invoke(User $user, LifecycleEventArgs $event)
{
// ...
}
}
This way you don't have to define a custom method
attribute in the
doctrine.orm.entity_listener
tag used to register the listener:
1 2 3 4 5 6 7 8 9 10 11 12
services:
# ...
App\EventListener\UserChangedNotifier:
tags:
-
name: 'doctrine.orm.entity_listener'
entity: 'App\Entity\User'
# before, when not defining the method name, Symfony looked for
# a method called after the event (e.g. 'postUpdate()') Now it
# will also look for an '__invoke()' method
event: 'postUpdate'
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
That's really nice !
Nice one !
I can't see a big improvement on listeners... I'm already using a zero-config for listeners now (with Symfony 3.4 or 4.3) just thanks to autoconfigure/autowiring
Very nice! I've use event listener with only __invoke() method before. Now I do not need to explicitly mention it in the config any more!
Cool, I will try it !
Great thanks
Kind of wish you had gone one step further and added an empty KernelEventListenerInterface. That would have allowed autoconfigure to do the tagging and removed the need for any explicit service configuration. And while a bit off-topic, it would also be nice to have a ControllerServiceArgumentsInterface.
Nice, thanks (y)
Cool !
Thanks! Does that mean __invoke is called for all events in a doctrine event listener? The arguments are the same for most events like postPersist, postUpdate, etc.