English spoken conference

Symfony 5: The Fast Track

A new book to learn about developing modern Symfony 5 applications.

Support this project

New in Symfony 4.4: Simpler Event Listeners

Contributed by
Alexander M. Turek
in #33851.

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ΒΆ

Contributed by
Thomas Calvet
in #32486.

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'

Comments

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.
Login with SymfonyConnect to post a comment