What is the kernel.terminate event?
It is the last event that is triggered in Symfony, just after the response has been sent to the client (only on php-fpm). This means that we can do some heavy lifting here because our response time is not affected. The client gets the response quickly and our processing will occur afterwards.
The Symfony SwiftMailer bundle does this by default, so we should be ok with emails, but my latest project needs to connect to various APIs on some events, and this takes quite some time.
In this post I will explain the method I use to make them run in the
For a primer about Symfony events, I recommend the official Symfony documentation
Custom events are trigerred from our own code, generally in the controller, and it goes something like this:
The event subscriber
Then we have an EventSubscriber that will listen to our custom events, in my case it’s called
ApiSubscriber and is located in
src/EventSubscriber. In this case it listens to two different events:
Configure the service
You will notice that I inject the container as it makes it easy to get everything we need, such as parameters or other services.
Don’t forget to configure the event subscriber in
app/config/services.yml like so:
Now our event subscriber is ready for action whenever we trigger the event from our controllers.
Handle your custom event
The event handling function is where the magic happens. Say when a new user is created, the
AppEvents::NEW_USER is triggered and the
ApiSubscriber::newUser function is called.
Here it is, I’ll explain later
So, from this code it is clear what happens. We first get the request from our custom event, then we set custom attributes on the request (simply because we need to retrieve them later from our static function) and finally we add a new listener (our static function, could also be an anonymous function) to the kernel.terminate event.
Do the job
The final piece of the puzzle is our
createThingOnApi static function that will do the real work.
Here it is:
This basically retrives our data from the request attributes, and then make some sort of curl request to an external API.
All done !
Do this and watch your response times go way down (only on php-pfm)
I’m not saying the is the best or even the only method to achieve this, just the one I personally use. the alternative would be some sort of mesasge queue, but it still seems like premature optimisation for an app of this size. If you have other options to achieve this, let me know in the comments on HN.