Symfony2.8->3.0: Request format override method

When I updated from Symfony 2.8 to Symfony 3.0, the code below did not work as intended. When you press “csv output”, &_format=csv is passed to the url and the page is redirected.
Originally, it will move to download the csv file. Looking at the documentation, it seems that the specs have changed between 2.8 and 3.0, but there seems to be no mention of how to change them.
How should I change it?

https://symfony.com/doc/3.0/routing.html

Controller

    /**
     * @Route("/", defaults={"_format"="html"}, requirements={"_format"="html|csv"})
     * @Method("GET")
     *
     * @Template("@AppBundle/Hq/Post/index.html.twig")
     */
    public function indexAction(Request $request)
    {
        if ($request->getRequestFormat() == 'html') {
            // At the time of html output
        } elseif ($request->getRequestFormat() == 'csv') {
            // At the time of csv output
            // Set file name, no pagination
            $request->attributes->set('filename', 'post_article.csv');
        }

index.html.twig

    <button type="submit" class="btn" name="_format" value="csv">
        <i class="icon-download"></i> CSV output
    </button>

index.csv.twig

{% autoescape false %}
{% if searchForm.content.vars.data -%}
    content,{{ searchForm.content.vars.data }}
{% endif %}
…
{% endautoescape %}

CsvListener

class CsvResponseListener
{
    /**
     * kernel.response Set the response at the time of CSV output in the event
     */
    public function onKernelResponse(FilterResponseEvent $event)
    {
        $request = $event->getRequest();
        $response = $event->getResponse();

        // Set the response at the time of CSV output in the event
        if ($request->getRequestFormat() === 'csv' && $response->getStatusCode() == 200) {
            // Convert response body to CRLF, SJIS-WIN
            $content = str_replace("n", "rn", $response->getContent());
            $content = mb_convert_encoding($content, 'SJIS-WIN', 'UTF-8');
            $response->setContent($content);

            // Get the file name
            $filename = $request->attributes->get('filename', 'download.csv');

            // Set header for file download
            $response->headers->set('Content-Type', 'application/octet-stream');
            $response->headers->set('Content-Transfer-Encoding', 'binary');
            $response->headers->set('Content-Disposition', 'attachment; filename="'.$filename.'"');
            $response->headers->set('Content-Length', strlen(bin2hex($content)) / 2);
        }
    }
}

services.yaml

    app.listener.csvResponseListener:
        class: AppBundleListenerCsvResponseListener
        tags:
            - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }

Answer

You simply need to add the slug {_format} to the route. If you have no other routes that will match '/html' or '/csv' then you should be able to just safely add the slug right in there:

/**
 * @Route("/{_format}", defaults={"_format"="html"}, requirements={"_format"="html|csv"})

Then on the front-end, you will need to add some javascript to change the action of the form to '/csv' when the button is clicked.

Leave a Reply

Your email address will not be published. Required fields are marked *