Uložení routy posledního requestu [symfony]

posted 28.08.2014

Scénář

Chci přesměrovat na poslední request. Mám formulář dostupný z více stránek a po odeslání chci uživatele vrátit na stránku, ze které na formulář přišel.

Řešení #1: HTTP Referer

Pravopisně správná varianta je Referrer, nicméně nenapadný překlep v RFC 1945 (specifikace HTTP/1.0) se rozšířil natolik, že v kontextu HTTP je většinou potřeba použít variantu Referer.

<?php

use Symfony\Component\HttpFoundation\RedirectResponse;

class Controller
{
    public function refererAction()
    {
        $referer = $request->headers->get('referer');
        return new RedirectResponse($referer);
    }
}

Potíží s HTTP Refererem je, že nemusí být v požadavku dostupný. Druhé řešení je o něco robustnější a ukládá poslední routu v session.

Řešení #2: Poslední routa v session

Spolehlivějším než spoléhat na HTTP_REFERER je uložit si poslední nalezenou routu do sessiony. Aby se uložila při každém požadavku, vytvoříme EventListener, který se vyvolá při každé kernel.request události. Na stejné události je navěšený i RouterListener, který se stará o vybrání správné routy. Je tedy potřeba nově vytvořenému dát menší prioritu, aby se stihla vybrat. RouterListener má prioritu 32, v konfiguraci je teda potřeba dát menší.

services:
    smf_example.last_route_event_listener:
        class: SmfBlog\ExampleBundle\EventListener\LastRouteListener
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 30 }
<?php

namespace SmfBlog\ExampleBundle\EventListener;

use Symfony\Component\HttpFoundation\Session;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernel;

class LastRouteListener
{

    public function onKernelRequest(GetResponseEvent $event)
    {
        // Do not save subrequests
        if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) {
            return;
        }

        $request = $event->getRequest();
        $session = $request->getSession();

        $routeName = $request->get('_route');
        $routeParams = $request->get('_route_params');
        if ($routeName[0] == '_') {
            return;
        }
        $routeData = ['name' => $routeName, 'params' => $routeParams];

        // Do not save same matched route twice
        $thisRoute = $session->get('this_route', []);
        if ($thisRoute == $routeData) {
            return;
        }
        $session->set('last_route', $thisRoute);
        $session->set('this_route', $routeData);
    }
}