44

我在尝试闪烁消息并将用户重定向回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/,它也会重定向到索引。为什么?

4

8 回答 8

41

这是 Naitsirch 和 Santi 他们的代码的替代版本。我意识到一个特质对于这个功能来说是完美的。还对代码进行了一些优化。我更喜欢返回所有参数,包括 slug,因为您在生成路线时可能需要这些参数。

此代码在 PHP 5.4.0 及更高版本上运行。当然,您可以将 trait 用于多个控制器。如果您将特征放在单独的文件中,请确保将其命名为与特征相同,遵循 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']
            ]
        ));
    }
}
于 2013-10-19T21:20:13.187 回答
18

对于 symfony 3.0,带有重定向到上一页的闪烁消息,这可以在控制器中完成。

           $request->getSession()
                ->getFlashBag()
                ->add('notice', 'success');
            $referer = $request->headers->get('referer');
            return $this->redirect($referer);
于 2016-12-13T05:34:16.067 回答
12

来自 Naitsirch 的消息显示在下一个 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);
}
于 2012-09-26T17:12:10.160 回答
9

这对我有用:

$this->redirect($request->server->get('HTTP_REFERER'));
于 2015-01-09T15:24:28.793 回答
4

我的网站上有类似的功能。它是多语言的。文章仅存在于单一语言环境中。当用户尝试切换到其他语言环境时,它应该重定向回上一页并闪烁消息,表明该页面/文章在请求的语言环境中不存在。

/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) {}
}
于 2015-07-05T11:03:25.223 回答
3

我只是设置了一个简单的应用程序,它似乎工作正常。我的 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
  • 用户输入的“皮卡丘”选项无效
  • 用户点击提交(POST 到 /create)
  • 应用程序拒绝该条目,添加 Flash 消息,并重定向回 /new
  • 用户看到 /new 和 flash 消息

需要检查的几件事:

  • 你的路线/demo/{entityId}/edit真的有效吗?(即,如果您在浏览器中输入它,它实际上会到达您期望的位置吗?)

  • 您是否将不同的重定向/转发链接在一起?我注意到当我有一个重定向到 URL 的控制器并且负责该 URL 的控制器也重定向到其他地方时,我得到了意外(但正确)的行为。我已经通过使用转发解决了这个问题。

也就是说,如果一切都失败了,你可以只使用控制器的 redirect() 方法来管理重定向:

public function createAction()
{
    ...
    return $this->redirect($this->generateUrl("pokemon_new"));
    ...
}
于 2012-08-10T01:20:32.873 回答
1

在这里,将其声明为服务,它会在您需要的任何时间和地点向您返回推荐人。没有特征,没有奇怪的依赖。

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

}
于 2016-08-11T10:54:06.037 回答
0

似乎您需要有一个有效负载来指向您的重定向。对我来说,这似乎是模糊的概念代码。我还建议您确保您的配置文件指向正确的重定向代码片段。检查您的服务器访问文件以确保它也启用了重定向。

于 2012-08-10T06:41:01.707 回答