Symfony2: Перенаправление на последний маршрут и флэш-сообщение?
У меня возникла небольшая проблема при попытке выполнить флэш-сообщение и перенаправить пользователя на предыдущую страницу в 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/
), оно перенаправляется на индекс. Почему?
Ответы
Ответ 1
Это альтернативная версия Найцирха и Санти их кода. Я понял, что черта будет идеальной для этой функциональности. Также немного оптимизирован код. Я предпочел вернуть все параметры, включая пули, потому что вам может понадобиться их при создании маршрута.
Этот код работает на 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']
]
));
}
}
Ответ 2
Сообщение от Найцирха, представленное в следующем 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);
}
Ответ 3
Для symfony 3.0, флэш-сообщение с перенаправлением на предыдущую страницу, это можно сделать в контроллере.
$request->getSession()
->getFlashBag()
->add('notice', 'success');
$referer = $request->headers->get('referer');
return $this->redirect($referer);
Ответ 4
Это работает для меня:
$this->redirect($request->server->get('HTTP_REFERER'));
Ответ 5
У меня есть аналогичные функции на моем сайте. Он многоязычный. Статьи существуют только в одном языке. Когда пользователь попытается переключиться на другой язык, он должен перенаправить на предыдущую страницу и флэш-сообщение о том, что эта страница/статья не существует в запрошенной языковой версии.
/en/article/3 -> /fr/article/3 (404) -> Redirect(/en/article/3)
Вот моя версия script, которая хорошо работает в средах 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) {}
}
Ответ 6
Я просто создал простое приложение, и, похоже, он работает нормально. Мой 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()
));
}
Поток идет:
- Пользователь переходит к /new
- Пользователь вводит неверную опцию "pikachu"
- Пользователь нажимает кнопку отправки (POST для создания/создания)
- Приложение отклоняет запись, добавляет флеш-сообщение и перенаправляет обратно в /new
- Пользователь видит/новый с флэш-сообщением
Несколько вещей, чтобы проверить:
-
Действительно ли ваш маршрут для /demo/{entityId}/edit
работает? (т.е. если вы вводите его в браузере, действительно ли он идет туда, где вы ожидаете?)
-
Вы объединяете разные переадресации/пересылки? Я заметил, что я получаю неожиданное (но правильное) поведение, когда у меня есть контроллер, который перенаправляет URL-адрес, и контроллер, ответственный за этот URL-адрес, также перенаправляет куда-то еще. Я исправил эту проблему, используя вместо нее.
Тем не менее, если все остальное не удается, вы можете просто использовать метод redirect() контроллера для управления перенаправлением:
public function createAction()
{
...
return $this->redirect($this->generateUrl("pokemon_new"));
...
}
Ответ 7
Здесь вы идете, объявляете это как сервис, и он будет возвращать вам референт где угодно и когда вам это нужно. Нет черт, нет странных зависимостей.
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;
}
}
Ответ 8
похоже, что вам нужно иметь полезную нагрузку для перенаправления. для меня это кажется неясным концептуальным кодом. Я также советую вам убедиться, что ваши файлы конфигурации указывают на правильный фрагмент кода перенаправления. Проверьте файл доступа к серверу, чтобы убедиться, что он также имеет перенаправленные адреса.
Ответ 9
Zero плюс Zéro égale... La Tête à Toto!