J'ai un petit problème en essayant de flasher un message et de rediriger l'utilisateur vers la page précédente dans Symfony 2.
J'ai un CRUD très simple. Lorsque je suis nouveau ou édité, je veux flasher un message si quelque chose ne va pas dans les méthodes de création/mise à jour respectives:
User --GET--> new
new --POST--> create (fails)
--REDIRECT--> new (with flash message)
Je fais ce qui suit:
$this->container->get('session')->setFlash('error', 'myerror');
$referer = $this->getRequest()->headers->get('referer');
return new RedirectResponse($referer);
Cependant, il ne redirige pas vers le bon référent! Même si la valeur du référent est correcte (par exemple: http://localhost/demo/2/edit/
), Il redirige vers l'index. Pourquoi?
Il s'agit d'une version alternative de Naitsirch et Santi leur code. J'ai réalisé qu'un trait serait parfait pour cette fonctionnalité. Également optimisé quelque peu le code. J'ai préféré rendre tous les paramètres, y compris les limaces, car vous pourriez en avoir besoin lors de la génération de l'itinéraire.
Ce code fonctionne sur PHP 5.4.0 et plus. Vous pouvez bien sûr utiliser le trait pour plusieurs contrôleurs. Si vous mettez le trait dans un fichier séparé, assurez-vous de le nommer de la même façon que le trait , après 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']
]
));
}
}
Le message de Naitsirch présenté dans la prochaine URL: https://github.com/symfony/symfony/issues/2951
Semble une bonne solution pour ce dont vous avez besoin:
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;
}
Puis avec une redirection:
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);
}
Pour symfony 3.0, message flash avec redirection vers la page précédente, cela peut être fait dans le contrôleur.
$request->getSession()
->getFlashBag()
->add('notice', 'success');
$referer = $request->headers->get('referer');
return $this->redirect($referer);
Cela fonctionne pour moi:
$this->redirect($request->server->get('HTTP_REFERER'));
J'ai des fonctionnalités similaires sur mon site. Il est multilingue. Les articles n'existent que dans un seul lieu. Lorsque l'utilisateur essaie de basculer vers d'autres paramètres régionaux, il doit rediriger vers la page précédente et un message flash indiquant que cette page/cet article n'existe pas sur les paramètres régionaux demandés.
/en/article/3 -> /fr/article/3 (404) -> Redirect(/en/article/3)
Voici ma version du script qui fonctionne bien sur les environnements dev
et 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) {}
}
Je viens de mettre en place une application simple, et cela semble bien fonctionner. Mon createAction () ressemble à ceci:
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()
));
}
Le flux va:
Quelques points à vérifier:
Votre itinéraire est-il pour /demo/{entityId}/edit
fonctionne réellement? (c.-à-d. si vous le saisissez dans le navigateur, est-ce qu'il va vraiment là où vous vous attendez?)
Enchaînez-vous ensemble différentes redirections/transferts? J'ai remarqué que j'obtiens un comportement inattendu (mais correct) lorsque j'ai un contrôleur qui redirige vers une URL, et le contrôleur responsable de cette URL redirige également ailleurs. J'ai résolu ce problème en utilisant à la place.
Cela dit, si tout le reste échoue, vous pouvez simplement utiliser la méthode redirect () du contrôleur pour gérer la redirection:
public function createAction()
{
...
return $this->redirect($this->generateUrl("pokemon_new"));
...
}
Voilà, déclarez cela comme un service et il vous sera renvoyé où et quand vous en aurez besoin. Pas de traits, pas de dépendances étranges.
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;
}
}
semble avoir besoin d'une charge utile pour que votre redirection pointe. cela me semble être un code conceptuel obscur. Je vous conseillerais également de vous assurer que vos fichiers de configuration pointent vers l'extrait de code de redirection correct. Vérifiez votre fichier d'accès au serveur pour vous assurer que les redirections sont également activées.