Symfony2: Перенаправление на последний маршрут и флэш-сообщение?

У меня возникла небольшая проблема при попытке прошивки сообщения и перенаправления пользователя на предыдущую страницу в Symfony 2 .

У меня очень простой CRUD. Когда новое или редактируемое, я хочу выпустить сообщение, если что-то пойдет не так в соответствующих методах создания / обновления:

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

Я делаю следующее:

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

Однако это не перенаправление на правильный реферер! Несмотря на то, что значение referrer верное (например: http://localhost/demo/2/edit/ ), он перенаправляет на индекс. Зачем?

Solutions Collecting From Web of "Symfony2: Перенаправление на последний маршрут и флэш-сообщение?"

Это альтернативная версия Найцирха и Санти их кода. Я понял, что черта будет идеальна для этой функциональности. Также немного оптимизирован код. Я предпочел вернуть все параметры, включая пули, потому что вам может понадобиться их при создании маршрута.

Этот код работает на PHP 5.4.0 и выше. Конечно, вы можете использовать признак для нескольких контроллеров. Если вы поместите этот признак в отдельный файл, убедитесь, что вы назовёте его таким же, как признак, после 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'] ] )); } } 

Сообщение от Найцирха представлено в следующем URL-адресе: https://github.com/symfony/symfony/issues/2951

Кажется хорошим решением для вас:

 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; } 

Затем с переадресацией:

 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); } 

Это работает для меня:

 $this->redirect($request->server->get('HTTP_REFERER')); 

У меня есть аналогичные функции на моем сайте. Он многоязычный. Статьи существуют только в одном языке. Когда пользователь попытается переключиться на другую локаль, он должен перенаправить на предыдущую страницу и флэш-сообщение о том, что эта страница / статья не существует в запрошенной языковой версии.

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

Вот моя версия скрипта, которая хорошо работает в средах dev и 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) {} } 

Для Symfony 3.0, флэш-сообщение с перенаправлением на предыдущую страницу, это можно сделать в контроллере.

  $request->getSession() ->getFlashBag() ->add('notice', 'success'); $referer = $request->headers->get('referer'); return $this->redirect($referer); 

Я просто создал простое приложение, и, похоже, он работает нормально. Мой createAction () выглядит так:

 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() )); } 

Поток идет:

  • Пользователь переходит к / новому
  • Пользователь вводит недопустимый вариант "pikachu"
  • Пользователь нажимает submit (POSTs to / create)
  • Приложение отклоняет запись, добавляет флеш-сообщение и перенаправляет обратно в / new
  • Пользователь видит / новый с флэш-сообщением

Несколько вещей, чтобы проверить:

  • Действительно ли работает ваш маршрут для /demo/{entityId}/edit ? (т. е. если вы вводите его в браузере, действительно ли он идет туда, где вы ожидаете?)

  • Вы объединяете разные переадресации / форварды? Я заметил, что я получаю неожиданное (но правильное) поведение, когда у меня есть контроллер, который перенаправляет URL-адрес, и контроллер, ответственный за этот URL-адрес, также перенаправляет куда-то еще. Я исправил эту проблему, используя вместо этого форварды.

Тем не менее, если все остальное не удается, вы можете просто использовать метод redirect () контроллера для управления перенаправлением:

 public function createAction() { ... return $this->redirect($this->generateUrl("pokemon_new")); ... } 

Здесь вы идете, объявляете это как услугу, и он вернет вам референт где угодно и когда захочет. Никаких черт, никаких странных зависимостей.

 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; } } 

похоже, вам нужно иметь полезную нагрузку для вашего перенаправления. для меня это кажется неясным концептуальным кодом. Я также советую вам убедиться, что ваши файлы конфигурации указывают на правильный фрагмент кода перенаправления. Проверьте файл доступа к серверу, чтобы убедиться, что он также активировал перенаправление.