Symfony2: przekierowanie na ostatnią trasę i flashowanie wiadomości?

Mam mały problem przy próbie flashowania wiadomości i przekierowania użytkownika z powrotem do poprzedniej strony w Symfony 2 .

Mam bardzo prosty CRUD. Gdy nowy, lub edytować, chcę flashować wiadomość, jeśli coś pójdzie nie tak w odpowiednich metod tworzenia/aktualizacji:

  1. User --GET--> new
  2. new --POST--> create (fails)
  3. --REDIRECT--> new (with flash message)

Robię co następuje:

  $this->container->get('session')->setFlash('error', 'myerror');
  $referer = $this->getRequest()->headers->get('referer');   
  return new RedirectResponse($referer);

Jednak nie jest to przekierowanie do właściwego referrera! Mimo że wartość referrer jest poprawny (np.: http://localhost/demo/2/edit/) przekierowuje do indeksu. Dlaczego?

 33
Author: Trix, 2012-08-10

8 answers

Jest to alternatywna wersja kodu Naitsirch I Santi. Zdałem sobie sprawę, że cecha będzie idealna dla tej funkcjonalności. Również nieco zoptymalizował kod. Wolałem oddać wszystkie parametry, w tym ślimaki, ponieważ możesz ich potrzebować podczas generowania trasy.

Ten kod działa na PHP 5.4.0 i nowszych. Możesz oczywiście użyć tej cechy dla wielu kontrolerów. Jeśli umieścisz cechę w oddzielnym pliku, upewnij się, że nadasz jej taką samą nazwę, jak cecha, Po PSR-0.

<?php
trait Referer {
    private function getRefererParams() {
        $request = $this->getRequest();
        $referer = $request->headers->get('referer');
        $baseUrl = $request->getBaseUrl();
        $lastPath = substr($referer, strpos($referer, $baseUrl) + strlen($baseUrl));
        return $this->get('router')->getMatcher()->match($lastPath);
    }
}

class MyController extends Controller {
    use Referer;

    public function MyAction() {
        $params = $this->getRefererParams();

        return $this->redirect($this->generateUrl(
            $params['_route'],
            [
                'slug' => $params['slug']
            ]
        ));
    }
}
 34
Author: Flip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-19 21:20:13

Wiadomość z Naitsirch przedstawiona w następnym adresie url: https://github.com/symfony/symfony/issues/2951

Wydaje się dobrym rozwiązaniem na to, czego potrzebujesz:

public function getRefererRoute()
{
    $request = $this->getRequest();

    //look for the referer route
    $referer = $request->headers->get('referer');
    $lastPath = substr($referer, strpos($referer, $request->getBaseUrl()));
    $lastPath = str_replace($request->getBaseUrl(), '', $lastPath);

    $matcher = $this->get('router')->getMatcher();
    $parameters = $matcher->match($lastPath);
    $route = $parameters['_route'];

    return $route;
}

Następnie z przekierowaniem:

public function yourFunctionAction()
{
    $ruta = $this->getRefererRoute();

    $locale = $request->get('_locale');
    $url = $this->get('router')->generate($ruta, array('_locale' => $locale));

    $this->getRequest()->getSession()->setFlash('notice', "your_message");   

    return $this->redirect($url);
}
 9
Author: Santi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-16 15:09:21

Dla symfony 3.0, wiadomość flash z przekierowaniem do poprzedniej strony, można to zrobić w kontrolerze.

           $request->getSession()
                ->getFlashBag()
                ->add('notice', 'success');
            $referer = $request->headers->get('referer');
            return $this->redirect($referer);
 7
Author: Kisz Na,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-13 05:34:16

To działa dla mnie:

$this->redirect($request->server->get('HTTP_REFERER'));
 5
Author: Victor Odiah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-09 15:24:28

Mam podobną funkcjonalność na mojej stronie. Jest wielojęzyczny. Artykuły istnieją tylko w jednym języku. Gdy użytkownik będzie próbował przełączyć się na inne ustawienia regionalne, powinien przekierować z powrotem do poprzedniej strony i komunikat flash, że ta strona / artykuł nie istnieje w żądanym ustawieniach regionalnych.

/en/article/3 -> /fr/article/3 (404) -> Redirect(/en/article/3)

Oto moja wersja skryptu, która działa dobrze na środowiskach dev i prod:

$referer = $request->headers->get('referer')

// 'https://your-domain.com' or 'https://your-domain.com/app_dev.php'
$base = $request->getSchemeAndHttpHost() . $request->getBaseUrl();

// '/en/article/3'
$path = preg_replace('/^'. preg_quote($base, '/') .'/', '', $referer);

if ($path === $referer) {
    // nothing was replaced. referer is an external site
} elseif ($path === $request->getPathInfo()) {
    // current page and referer are the same (prevent redirect loop)
} else {
    try {
        // if this will throw an exception then the route doesn't exist
        $this->container->get('router')->match(
            // '/en/hello?foo=bar' -> '/en/hello'
            preg_replace('/\?.*$/', '', $path)
        );

        // '/app_dev.php' . '/en/article/3'
        $redirectUrl = $request->getBaseUrl() . $path;

        return new RedirectResponse($redirectUrl);
    } catch (\Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {}
}
 4
Author: moldcraft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-06 21:15:42

Właśnie skonfigurowałem prostą aplikację i wydaje się, że działa dobrze. Moje createAction () wygląda tak:

public function createAction()
{
    $entity  = new Pokemon();
    $request = $this->getRequest();
    $form    = $this->createForm(new PokemonType(), $entity);
    $form->bindRequest($request);

    if ($entity->getName() == "pikachu")
    {
        $this->container->get("session")->setFlash("error", "Pikachu is not allowed");
        $url = $this->getRequest()->headers->get("referer");
        return new RedirectResponse($url);
    }

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getEntityManager();
        $em->persist($entity);
        $em->flush();

        return $this->redirect($this->generateUrl('pokemon_show', array('id' => $entity->getId())));

    }

    return $this->render('BulbasaurBundle:Pokemon:new.html.twig', array(
        'entity' => $entity,
        'form'   => $form->createView()
    ));
}

Przepływ płynie:

  • użytkownik przechodzi do / new
  • Użytkownik wprowadza nieprawidłową opcję "pikachu"
  • User clicks submit (POSTs to /create)
  • Aplikacja odrzuca wpis, dodaje wiadomość flash i przekierowuje z powrotem do / new
  • użytkownik widzi / nowy z Komunikatem flash

Kilka rzeczy do sprawdzenia:

  • Czy Twoja trasa /demo/{entityId}/edit jest rzeczywiście pracujesz? (tzn. jeśli wpiszesz go w przeglądarkę, To czy rzeczywiście trafi tam, gdzie się tego spodziewasz?)

  • Czy łączysz ze sobą różne przekierowania / do przodu? Zauważyłem, że otrzymuję nieoczekiwane (ale poprawne) zachowanie, gdy mam kontroler, który przekierowuje na adres URL, a kontroler odpowiedzialny za ten adres URL przekierowuje również gdzieś indziej. Naprawiłem ten problem, używając zamiast tego forwards.

To powiedziawszy, jeśli Wszystko inne zawiedzie, możesz po prostu użyć kontrolera metoda redirect() do zarządzania przekierowaniem:
public function createAction()
{
    ...
    return $this->redirect($this->generateUrl("pokemon_new"));
    ...
}
 3
Author: Thomas Kelley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-10 01:20:32

Proszę, zadeklaruj to jako usługę, a zwróci ci referer gdziekolwiek i kiedykolwiek go potrzebujesz. Żadnych cech, żadnych dziwnych zależności.

class Referer
{

    /** @var RequestStack */
    private $requestStack;

    /** @var RouterInterface */
    private $router;

    public function __construct(RequestStack $requestStack, RouterInterface $router)
    {
        $this->requestStack = $requestStack;
        $this->router       = $router;
    }

    public function getReferer() : string
    {
        $request = $this->requestStack->getMasterRequest();

        if (null === $request)
        {
            return '';
        }

        //if you're happy with URI (and most times you are), just return it
        $uri = (string)$request->headers->get('referer');

        //but if you want to return route, here you go
        try
        {
            $routeMatch = $this->router->match($uri);
        }
        catch (ResourceNotFoundException $e)
        {
            return '';
        }

        $route = $routeMatch['_route'];

        return $route;
    }

}
 1
Author: ex3v,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 10:54:06

Wygląda na to, że musisz mieć ładunek, aby przekierowanie wskazywało na. wydaje mi się to niejasnym kodem koncepcyjnym. Radzę również upewnić się, że pliki konfiguracyjne wskazują poprawny fragment kodu przekierowania. Sprawdź swój plik dostępu do serwera, aby upewnić się, że ma włączone przekierowania.

 0
Author: Joseph Hightower,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-01 16:47:22