Craft CMS で会員限定ページを作成してみよう(閲覧制限編)

これは Craft CMS Advent Calendar 2017 23日目の記事です。

前回 Craft CMS で「会員制サイト」を作成するにあたり、フロントエンドでのユーザー登録やログイン・ログアウトを実装しました。今回は、ログイン中のユーザーだけが見れる閲覧制限ページの作り方をご紹介しますので、あらかじめサンプルユーザーを作成しておいてください。

ログインを必須にするには

Craft CMS のフロントエンドでログインしているかどうかをチェックするには、 {% requireLogin %} タグを利用します。

{% extends "_layout" %}

{# 未ログイン状態であれば、ログイン画面へリダイレクト #}
{% requireLogin %}

{% block content %}
  {# 中略 #}
{% endblock %}

任意のテンプレートの先頭行付近でレイアウト用のテンプレートを指定するハズですので、{% extends %} タグに続けて追加しておくとよいでしょう。

ユーザー情報の編集画面を作成

新しく craft/templates/members/editprofile.twig を作成し、 {% requireLogin %} タグを含めたコードを記述します。

{% extends "_layout_members" %}

{# 未ログイン状態であれば、ログイン画面へリダイレクト #}
{% requireLogin %}

{% block content %}
  <div class="container mt-5">
    <div class="row">
      <div class="col-md-6 offset-md-3">
        <h1 class="h2">プロフィールの編集</h1>

        <form method="post" accept-charset="UTF-8" enctype="multipart/form-data">
          {{ getCsrfInput() }}
          <input type="hidden" name="action" value="users/saveUser">
          <input type="hidden" name="redirect" value="/members/editprofile">
          <input type="hidden" name="userId" value="{{ currentUser.id }}">

          <div class="form-group">
            <div class="form-inline">
              <div class="form-group">
                <label for="lastName" class="col-form-label">姓</label>
                <input type="text" id="lastName" name="lastName" value="{{ currentUser.lastName }}" class="form-control mx-2">
                <label for="firstName" class="col-form-label ml-3">名</label>
                <input type="text" id="firstName" name="firstName" value="{{ currentUser.firstName }}" class="form-control mx-2">
              </div>
            </div>
          </div>

          <div class="form-group">
            <label for="lastName" class="col-form-label">プロフィール画像</label>
            <div class="row">
              <div class="col-md-9">
                <input type="file" name="userPhoto" value="{{ (currentUser.photoUrl ? 'Change Photo' : 'Upload') }}" class="form-control">
              </div>

              <div class="col-md-3">
                <img src="{{ (currentUser.photoUrl ? currentUser.photoUrl : 'http://via.placeholder.com/100x100') }}" class="rounded mx-auto d-block" id="currentUserPhoto" />
                {% if currentUser.photoUrl %}
                  <button class="btn btn-sm btn-danger btn-block mt-1" id="deleteUserPhotoAction">画像を削除</button>
                  <input type="hidden" name="deleteUserPhoto" value="">
                {% endif %}
              </div>
            </div>
          </div>

          <button class="btn btn-primary btn-block" type="submit">上記の内容でプロフィールを保存</button>
        </form>
      </div>
    </div>
  </div>

  {% if currentUser.photoUrl %}
    <script>
      (function() {
        // 「画像を削除」ボタンのクリックイベント
        $('#deleteUserPhotoAction').on('click', function(e) {
          e.preventDefault();
          $('[name="deleteUserPhoto"]').val('zap');
          $('#currentUserPhoto').attr('src', 'http://via.placeholder.com/100x100');
          $(this).hide();
        });
      })();
    </script>
  {% endif %}
{% endblock %}

ファイル選択の入力項目を含むため enctype="multipart/form-data" をセットする他、 input[name="action"]input[name="userId"] あたりに気をつければ、一般的なフォームのマークアップになります。

なお、ユーザー画像の登録・削除に関する箇所は、下記を参考にしました。

assets - Allow user to change or delete their photo for their profile from the front end - Craft CMS Stack Exchange
https://craftcms.stackexchange.com/questions/1011/allow-user-to-change-or-delete-their-photo-for-their-profile-from-the-front-end

新しい画像を選択した際に File API でプレビューを表示させるなど、お好みで調整を加えてください。

トップページのメニューにリンクを追加

前回修正した craft/templates/index.twig のログイン状況に伴う分岐処理に、プロフィール編集画面へのリンクを追加します。

{% if currentUser %}
  ようこそ {{ currentUser.username }} さん<br>
  <a href="/members/editprofile">プロフィールの編集</a><br>
  <a href="{{ logoutUrl }}">ログアウト</a>
{% else %}
  <a href="{{ loginUrl }}">ログイン</a><br>
  <a href="/members/register">ユーザー登録</a>
{% endif %}

実際にログインして、動作を確認してみてください。

所属するユーザーグループで分岐するには

ログイン中のユーザーが特定のグループに所属しているかは currentUser.isInGroup('ユーザーグループのハンドル') でチェックできます。

{% extends "_layout" %}

{# 未ログイン状態であれば、ログイン画面へリダイレクト #}
{% requireLogin %}

{# ハンドル名 'premium_member' のグループに所属していなければ、リダイレクト #}
{% if not currentUser.isInGroup('premium_member') %}
  {% redirect '/invitation/premium_service' %}
{% endif %}

{% block content %}
  {# 中略 #}
{% endblock %}

サンプルでは、ハンドル名が 'premium_member' というユーザーグループに所属していなければ、サービスの紹介ページにリダイレクトするといったケースを想定しています。

まとめ

Craft CMS で会員制サイトを構築するにあたり、閲覧制限をする際のポイントについてまとめてみました。

今回ご紹介した所属するユーザーグループによる判別以外にも、ユーザーのカスタムフィールド(プロファイル タブに表示される入力項目)の値で分岐するなど、柔軟にカスタマイズできるのは魅力ですね。