Asynchronous-ish Events using kernel.terminate

Recently I’ve expanded my symfony2 awareness by diving into the Event Dispatcher docs and find myself using it alot to keep my code nicely separated. Some of these events have a fairly long execution time so I looked around to see if there was any way to execute these events after the response so the response time would appear faster.

Sure enough, Symfony2 has a terminate event that is called after the response has been sent. The post Handling Symfony2 Events Asynchronously by Dave Marshall mentions this method but doesn’t provide any code showing how to do it. Reading the post Login Redirection Revisited by Dustin Dobervich helped me figure out how to make this work.

The code just has some dummy placeholders but you get the idea.

namespace Avro\DemoBundle\Listener;

use Doctrine\ORM\EntityManager;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\KernelEvents;
use Avro\DemoBundle\Event\CustomEvent;

class CustomListener
{
    protected $em;
    protected $dispatcher;

    public function __construct(EntityManager $em, EventDispatcher $dispatcher) {
        $this->em = $em;
        $this->dispatcher = $dispatcher;
    }

    public function customMethod(CustomEvent $customEvent)
    {
        $em = $this->em;

        $this->dispatcher->addListener(KernelEvents::TERMINATE, function(Event $event) use ($customEvent, $em) {
             //...your listener code
             // $object = $customEvent->getObject();
             // $em->persist($object);
        });

    }
}
// config.yml
services:
    avro_demo.custom.listener:
        class: Avro\DemoBundle\Listener\CustomListener
        arguments: ["@doctrine.orm.entity_manager", "@event_dispatcher"]
        tags:
            - { name: kernel.event_listener, event: avro_demo.custom_event, method: customMethod }
<?php
// Avro/DemoBundle/Event/CustomEvent.html"brush: php; auto-links: false;">
    namespace Avro\DemoBundle\Entity\CustomManager;

    use Avro\DemoBundle\Event\CustomEvent;

...

    // fire the event, could be in your controller, form handler, whatever
    $dispatcher = $this->eventDispatcher;
    $dispatcher->dispatch('avro_demo.custom_event', new CustomEvent($object);

And that’s it! The custom method is now executed after the Response is sent. Let me know if you have any suggestions on improving this method. Comments appreciated!

You can leave a response, or trackback from your own site.

Leave a Reply