How to disable the Listeners in Symfony

18 / 04 / 2020

If you’re using Symfony since few times you probably use some event listeners like the doctrine events or the kernel events.

The idea is simple, you want to do some stuff when the event is fired for example : send a notification when a User is created, log some information when a specific Exception is thrown, move an image in a specific directory when it’s uploaded…

This concept is called the design pattern observer (do something when an event is dispatched).

In a big application, the same event can trigger many differents action and you can have side effects, the question is: “how can I disable an event listener ?”.

99% of the time you need to trigger the event and you need to do the action related to the event but how to cancel the action to manage the remaining 1%, if doctrine have a method to remove listener it’s not the case for kernel events or any others events, so you need to create your own logic to do this.

Most of the time the class that listens the event have a supports method that checks if the conditions are fulfilled to execute the action.

It could be something like :

or

Our plan is to add a property enabled (true by default) in addition to their control, our both supports methods will also check that enabled is true and I think you got it when we want to disable our listeners we will change the value of enabled to become false.

From there we have to change the enabled value anywhere in our application and to do this we will use the same concept as our previous listeners.

Use the design pattern observer and to do this we will use the Event Dispatcher component in only 4 steps !

1. Create the event itself

2. Create the method to toggle $enabled from true to false

I will put the logic in a Trait and makes our both Listeners use our Trait. In my opinion, Traits are useful to avoid duplication code.

3. Make our Listeners listening our brand new Event DisableListenerEvent

An easy way is to tag our listeners with an Interface to told to Symfony “Hey Symfony ! Any class with this Interface should listen this event.”

We will put the logic to told this to symfony in Kernel::build method but it can be in services.yaml with the _instanceof feature.

To be sure that this method exists in the listeners our Interface will have a method disable

🎉 Yeahhhh !!! Thanks to Symfony and the amazing people behind, at this point any class that implements DisableListeningInterface will listen the DisableListenerEvent and execute the method disable when the event is fired.

4. Dispatch the Event

And the job is done 🚀🚀🚀

Thanks for reading, I hope you liked it, don't forget to share it !
LinkedIn Twitter