create filter in controller symfony2

Sometimes you need to make changes to the Response object, after it is returned by your controller, but before it is rendered as output to the client (e.g. the browser). You may want to set some extra response headers, or "completely mess up the content" of the response. You can accomplish this by creating an event listener that listens to the kernel.response event. I give you a sample event listener which changes the Content-Type header in case the requested format is json and the browser’s accepted response format contains "text/html" in that case, at least in my experience, the browser doesn’t render the JSON string as plain text when the status code is 4xx or 5xx. So in these situations, the event listener changes the “Content-Type” to “text/plain”, to be sure you always get decent output in the browser.

Put the event listener in, for example /src/Acme/DemoBundle/EventListener/ResponseListener.php:

  
namespace Acme\DemoBundle\EventListener;
 
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
 
class ResponseListener
{
    public function onKernelResponse(FilterResponseEvent $event)
    {
        $request = $event->getRequest();
 
        // only do something when the requested format is "json"
        if ($request->getRequestFormat() != 'json') {
            return;
        }
         
        // only do something when the client accepts "text/html" as response format
        if (false === strpos($request->headers->get('Accept'), 'text/html')) {
            return;
        }
         
        // set the "Content-Type" header of the response
        $event->getResponse()->headers->set('Content-Type', 'text/plain');
    }
}

Now define the ResponseListener as a service in /src/Acme/DemoBundle/Resources/services.xml:

  
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
    <services>
        <service id="acme.filter_response_listener" class="Acme\DemoBundle\EventListener\ResponseListener">
            <tag name="kernel.event_listener" event="kernel.response" method="onKernelResponse" />
        </service>        
    </services>
</container>


Notice the “tag” tag, by which the kernel recognizes this service as an event listener. The event attribute tells the kernel which event this listener listens to. The “method” attribute tells which method should be called when the kernel.response event occurs.

In case you don’t want any other events to tamper with the Response, add a call to $event->stopPropagation().

Comments

  1. Good stuff! Thanks for sharing this.

    Symfony's events are really powerful but I've yet to find a case where I needed to hook into the response event. Have you and what was your use case?

    ReplyDelete

Post a Comment

Popular posts from this blog

ubuntu package installation

Drupal Bootstrap Database

How to fix 500 internal privoxy error