category

Craft CMS で redirectInput とrequireLogin をつかったログイン後のリダイレクトを考える #craftcms

2020-05-12

Craft CMS にはログインした後とかにリダイレクト先を指定できる関数 redirectInput がある。

Functions | Craft 3 Documentation
https://docs.craftcms.com/v3/d...

ログインフォームとか会員登録フォームとかそういうところで使うことができる。

User Registration Form | Craft 3 Documentation
https://docs.craftcms.com/v3/d...
<form method="post" accept-charset="UTF-8">
    {{ csrfInput() }}
    {{ actionInput('users/save-user') }}
    {{ redirectInput('') }}

これを使うことで自由にリダイレクトを制御することができる。

requireLogin を使うと craft.app.user.returnUrl で元ページにリダイレクトできる

例えば会員制サイトとかであればページによってログイン必須のページには {% requireLogin %} タグをおくことで、ページに来たユーザーがログインしているかどうか?をみて、ログインページにリダイレクトしてくれる。

Tags | Craft 3 Documentation
https://docs.craftcms.com/v3/d...

これを使うことで、ログイン必要なページからログインフォームに行ってログインする、という流れを作ることができる。

{% requireLogin %} タグを使ってリダイレクトしてくる時は craft.app.user.returnUrl を使うことで、遷移元のページを覚えておいて、リダイレクトすることができる。

{{ redirectInput(craft.app.user.returnUrl) }}

requireLogin を使えない場合に自サイトの元ページを判定してリダイレクトする

ただ、ログインフォームへの遷移元で、{% requireLogin %} タグを使えない時もあると思う。

そういう時は遷移元からのリファラ craft.app.request.referrer を使って判定することもできそう。

{% if craft.app.request.referrer matches '/^https:\\/\\/example.com\\//' %}
{{ redirectInput(craft.app.request.referrer) }}
{% else %}
{{ redirectInput('/') }}
{% endif %}

matches のところは直書きじゃなくて、動的に自サイトのものと判定できるようにした方がいい気はするが、、、

【追記20200512-0950】
@BUN に教えてもらってこんな感じで動的に判定できそう!!

{% if craft.app.request.referrer matches '/^' ~ siteUrl | replace('/', '\\/') ~ '/' %}
{{ redirectInput(craft.app.request.referrer) }}
{% else %}
{{ redirectInput('/') }}
{% endif %}

【追記20200512-0950 ここまで】

【追記20200512-1030】
@tinybeans に教えてもらった別案はこんな感じで判定できそう!!

{% if craft.app.request.referrer starts with siteUrl %}
{{ redirectInput(craft.app.request.referrer) }}
{% else %}
{{ redirectInput('/') }}
{% endif %}

https://twig.symfony.com/doc/2.x/templates.html#expressions

なるほどなー!

【追記20200512-1030 ここまで】

マッチした場合はそのリファラにしてそれ以外はトップにリダイレクトするという感じにしてみた。

craft.app.request.hogehoge は色々あるんだけど、何があるのかがいまいちわからない、、、

requireLogin をつかって craft.app.user.returnUrl を使えるようにする

craft.app.user.returnUrl を使えれば自サイトであればそのままリダイレクトできるし、それ以外の時はサイトトップにリダイレクトすることができる。

なので、ログインフォームへのリンクなど requireLogin をつかって実装する案を @BUN に教えてもらった。

たとえばログインフォームへのリンクを

<a href="{{ url(craft.app.request.url,'loginchek=1') }}">ログイン</a>

のような感じで設定する。

url() はURLを組み立てることができる。

Functions | Craft 3 Documentation
https://docs.craftcms.com/v3/d...

なので、今のURL craft.app.request.url に logincheck=1 のパラメータがつくようにURLを組み立てる。

これでリンクは https://example.com/hogehoge?logincheck=1 のような感じで今いるページにパラメータがついた感じなる。

そのうえで、今のリンク元のテンプレートに以下のように記載しておく。

{% if craft.app.request.getQueryParam("logincheck") == 1 %}
  {% set redirectParam = craft.app.request.getQueryParam("logincheck") %}
  {% requireLogin %}
{% else %}
  {# redirectParam はなし #}
{% endif %}

これで一旦自ページにパラメータ付きでリンクされ、パラメータ有無のチェックがされて、パラメータがあるから、 requireLogin が実行され、ログインページへリダイレクトされる。

ログイン後の戻り先のURLを調整する

ログインページへ遷移した後に、リダイレクト先は craft.app.request.url を使うことで自サイトから離脱せずにリダイレクトができるようになる。
ただ、ログインチェック用のパラメータがついてしまってリダイレクトが戻されることになる。

このパラメータは不要なので、

{% set redirectURL = craft.app.user.returnUrl|replace('/(\\?|&)logincheck=1/', "") %}
  {{ redirectInput(redirectURL) }}

のような感じで余計なパラメータは削除して戻すことができる。

url() でログインフォームへのリンクを生成しているので、 logincheck のパラメータは元のページのURLに何かしらパラメータがついてれば最後(&logincheck)に付与され、ついていなければ最初(?logincheck)に付与される。

なので、このどちらかのパターンを削除して redirectInput に指定すると良さそう。

GoogleAnalytics の計測とかがどうなるか?とかがきになるところもあるし、なんかもっといい方法がありそうな気がするが、とりあえず考えた方法としてはこんなところで。