У меня возникла небольшая проблема при попытке прошивки сообщения и перенаправления пользователя на предыдущую страницу в Symfony 2 .
У меня очень простой CRUD. Когда новое или редактируемое, я хочу выпустить сообщение, если что-то пойдет не так в соответствующих методах создания / обновления:
User --GET--> new
new --POST--> create (fails)
--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/
), он перенаправляет на индекс. Зачем?
Это альтернативная версия Найцирха и Санти их кода. Я понял, что черта будет идеальна для этой функциональности. Также немного оптимизирован код. Я предпочел вернуть все параметры, включая пули, потому что вам может понадобиться их при создании маршрута.
Этот код работает на 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() )); }
Поток идет:
Несколько вещей, чтобы проверить:
Действительно ли работает ваш маршрут для /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; } }
похоже, вам нужно иметь полезную нагрузку для вашего перенаправления. для меня это кажется неясным концептуальным кодом. Я также советую вам убедиться, что ваши файлы конфигурации указывают на правильный фрагмент кода перенаправления. Проверьте файл доступа к серверу, чтобы убедиться, что он также активировал перенаправление.