create filter in controller symfony2

1
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().

1 comments:

Tobias Sjösten said...

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?

Post a Comment

From Around the Web