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 のコードの代替バージョンです。この機能には特性が最適であることに気付きました。また、コードを多少最適化しました。ルートを生成するときにスラッグが必要になる可能性があるため、スラッグを含むすべてのパラメーターを返すことを好みました。

このコードは 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']
            ]
        ));
    }
}
于 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

次の URL にある Naitsirch からのメッセージ: 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 に答える
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 に移動します
  • ユーザーが「ピカチュウ」の無効なオプションを入力しました
  • ユーザーが送信をクリックする (/create への POST)
  • アプリケーションはエントリを拒否し、フラッシュ メッセージを追加して、/new にリダイレクトします。
  • /new が表示され、フラッシュ メッセージが表示される

いくつかの確認事項:

  • /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 に答える