EC-CUBE4でログイン成功時に直前まで見ていた画面へ戻る方法

EC-CUBE4ではログインする場合、EC-CUBE2とは違いログイン画面を経由させる必要があります。

また、ログイン成功後は必ずサイトのトップページへ戻ってしまいます。

サイトの作りにもよりますが、例えばログイン後は前に見ていた画面を表示して欲しいという要望があった場合、 以下のカスタマイズを行うことで実現可能となります。

EC-CUBE3では以下の記事で対応方法を書いています。

amidaike.hatenablog.com

EC-CUBE4.0.1を対象に説明します。

まず、MypageControllerのコンストラクタに対してRequestStackクラスを宣言します。

  • src/Eccube/Controller/Mypage/MypageController.php
/**
 * @var RequestStack
 */
protected $requestStack;

/**
 * MypageController constructor.
 *
 * @param OrderRepository $orderRepository
 * @param CustomerFavoriteProductRepository $customerFavoriteProductRepository
 * @param CartService $cartService
 * @param BaseInfoRepository $baseInfoRepository
 * @param PurchaseFlow $purchaseFlow
 * @param RequestStack $requestStack
 */
public function __construct(
    OrderRepository $orderRepository,
    CustomerFavoriteProductRepository $customerFavoriteProductRepository,
    CartService $cartService,
    BaseInfoRepository $baseInfoRepository,
    PurchaseFlow $purchaseFlow,
    RequestStack $requestStack
)
{
    $this->orderRepository = $orderRepository;
    $this->customerFavoriteProductRepository = $customerFavoriteProductRepository;
    $this->BaseInfo = $baseInfoRepository->get();
    $this->cartService = $cartService;
    $this->purchaseFlow = $purchaseFlow;
    $this->requestStack = $requestStack;
}

その後、MypageControllerにあるlogin関数を修正します。

/**
 * ログイン画面.
 *
 * @Route("/mypage/login", name="mypage_login")
 * @Template("Mypage/login.twig")
 */
public function login(Request $request, AuthenticationUtils $utils)
{
    if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
        log_info('認証済のためログイン処理をスキップ');

        return $this->redirectToRoute('mypage');
    }

    /* @var $form \Symfony\Component\Form\FormInterface */
    $builder = $this->formFactory
        ->createNamedBuilder('', CustomerLoginType::class);

    $builder->get('login_memory')->setData((bool)$request->getSession()->get('_security.login_memory'));

    if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
        $Customer = $this->getUser();
        if ($Customer instanceof Customer) {
            $builder->get('login_email')
                ->setData($Customer->getEmail());
        }
    }

    $event = new EventArgs(
        [
            'builder' => $builder,
        ],
        $request
    );
    $this->eventDispatcher->dispatch(EccubeEvents::FRONT_MYPAGE_MYPAGE_LOGIN_INITIALIZE, $event);

    $form = $builder->getForm();

    // ログイン前の画面へ戻す
    $error = $utils->getLastAuthenticationError();
    if (!$error) {
        // ログインエラーがなければ戻り先をセット
        $referer = $request->headers->get('referer');

        if ($referer) {
            // refererチェック
            $referers = parse_url($referer);
            if ($referers['host'] == $request->getHost()) {
                // ホストが同一であればrefererをセット
                $requestStackUri = $this->requestStack->getMasterRequest()->getUri();

                if ($request->getUri() == $requestStackUri) {
                    // ログイン画面遷移直前のuriをセット
                    $this->setLoginTargetPath($referer);
                } else {
                    // ログイン必須画面のuriをセット
                    $this->setLoginTargetPath($requestStackUri);
                }
            }
        }
    }

    return [
        'error' => $error,
        'form' => $form->createView(),
    ];
}

修正箇所は、

// ログイン前の画面へ戻す
$error = $utils->getLastAuthenticationError();
if (!$error) {
    // ログインエラーがなければ戻り先をセット
    $referer = $request->headers->get('referer');

    if ($referer) {
        // refererチェック
        $referers = parse_url($referer);
        if ($referers['host'] == $request->getHost()) {
            // ホストが同一であればrefererをセット
            $requestStackUri = $this->requestStack->getMasterRequest()->getUri();

            if ($request->getUri() == $requestStackUri) {
                // ログイン画面遷移直前のuriをセット
                $this->setLoginTargetPath($referer);
            } else {
                // ログイン必須画面のuriをセット
                $this->setLoginTargetPath($requestStackUri);
            }
        }
    }
}

return [
    'error' => $error,
    'form' => $form->createView(),
];

になります。ログイン前のrefererを取得し、ログイン成功時に直前まで見ていた画面へ戻すようにしています。ただし、ログインが必要な画面を直接指定された場合、refererを取得するとログインに成功してもrefererで指定した画面に遷移してしまうため、

$this->requestStack->getMasterRequest()->getUri();

と本来指定されているURLを取得し、比較する事でログイン成功後の遷移先を変更するようにセットしています。

refererが取得できない環境は諦めてください。

あと、login.twigも変更する必要があります。以下のソースをlogin.twigのform内に追加します。

  • src/Eccube/Resource/template/default/Mypage/login.twig
<form name="login_mypage" id="login_mypage" method="post" action="{{ url('mypage_login') }}">
{% if app.session.flashBag.has('eccube.login.target.path') %}
    {% for targetPath in app.session.flashBag.peek('eccube.login.target.path') %}
        <input type="hidden" name="_target_path" value="{{ targetPath }}" />
    {% endfor %}
{% endif %}

以上の対応でログイン成功後は、直前まで見ていた画面へ遷移するようになります。