【プラグインなし】WordPressのユーザー機能を活用した会員機能の実装

2022/06/19に公開

はじめに

WordPressでの会員機能実装として真っ先にプラグインの導入が頭に浮かんだのですが、要件に合うものがなくてどうしたものか…と考えていた時に
WordPressのユーザー権限を活用してやればできそうじゃない?
と思い至り、実際にやってみたというお話です。

要件について

  • 一つの共通ID・パスワードを設定し、その情報でログインしたユーザーのみが閲覧できるページ領域を構築する
  • 会員用ログインページ(/login)は自由なデザインが組める
  • ログインせずに会員領域のページにアクセスしようとすると会員用ログインページにリダイレクトする
  • 会員領域ページにあるダウンロード可能ファイルは、最悪、会員以外に漏れても問題ない
  • WordPressの購読者権限を使う予定がない→WordPressのダッシュボードに入らせないようにして、フロント側の会員機能のみに活用する
  • メールアドレスはIDの代わりに使用できないようにする
  • ログアウトボタンで会員がログアウト→一般ページトップへ戻る

簡易構築イメージ

それでは早速、作っていく手順をご紹介します。

手順1:WordPressで購読者権限のアカウントを作成

管理者権限のユーザーでWordPressにログイン後、会員アカウント用の購読者権限ユーザーを1人分新規追加します。
メールアドレスは使用しないので、明らかに実在しないようなメールアドレス【test@test.comなど】で登録して問題ないと思います。

手順2:会員領域のページを作成

会員限定で閲覧できるページを作っていきます。
後程、ログイン判定用の記述を入れるようにしますが、とりあえずそのままコーディングしていきます。
その際、ログアウトボタンも設置しておきましょう。

手順3:会員用ログインページをコーディング

固定ページで会員用ログインというタイトルのページを新規作成し、URLスラッグを設定します。
WordPressの有効化しているテーマディレクトリでpage-{slug}.phpのファイルを作成する・専用テンプレートファイルを作ってテンプレート選択で読み込む…などで会員用ログインページのファイルを準備してコーディングしていきます。
ID入力欄とパスワード入力欄、ログインボタンをコーディングする感じですね。

また、ここではmemberというスラッグの固定ページが会員用ページのトップとして、ログインに成功したらリダイレクトされる先という例で考えていきます。

必ず行うこと

  • form要素のmethodはPOSTにする
  • input要素のhiddenでログイン成功時のURLをvalueに入れて送信内容に含める
<input type="hidden" value="<?php echo esc_url(home_url('/member')); ?>" name="redirect">
  • wp_nonce_fieldsを送信内容に含めてCSRF対策をしておく
<?php wp_nonce_field('member-login-action', 'member-login-field'); ?>

nonceでform内容が現在のWebページから送られたものだということを照合させるのに必要ですね。

手順4:ログイン時の処理

functions.phpに以下のような処理を加えていきます。

<?php
// 会員用ログイン処理
function member_user_login() {
remove_filter( 'authenticate', 'wp_authenticate_email_password', 20 );
  $user_login = isset($_POST['user_login']) ?sanitize_text_field($_POST['user_login']) : '';
  $user_pass = isset($_POST['user_pass']) ? sanitize_text_field($_POST['user_pass']) : '';
  $redirect = isset($_POST['redirect']) ? esc_url($_POST['redirect']) : '';

  // ログイン認証
  $creds = array(
    'user_login' => $user_login,
    'user_password' => $user_pass,
  );
  $user = wp_signon($creds);

  //ログイン失敗時
  if (is_wp_error($user) || $user->caps['administrator']) { ?>
    <?php if ($user->caps['administrator']) {
      wp_logout();
    } ?>
    <p>入力したログイン情報が間違っています</p>
    <a href="<?php echo esc_url(home_url('/login')); ?>">ログイン画面へ戻る</a>
<?php exit; }

  //ログイン成功時 
  wp_safe_redirect($redirect);
  exit;
  return;
}

add_action('after_setup_theme', function () {
  if (isset($_POST['submit']) && $_POST['submit'] === 'login' && isset($_POST['redirect'])) {

    // nonceチェック
    if (!isset($_POST['member-login-field'])) return;
    if (!wp_verify_nonce($_POST['member-login-field'], 'member-login-action')) return;

    // ログインフォームからの送信時処理
    member_user_login();
  }
});

流れとしては…
会員用ログインページからID・パスワード・リダイレクトの送信内容を受け取る

IDとパスワードを配列に格納し、wp_signonで認証処理へ移行

途中でnonceチェックを入れ、会員用ログインページからのものかを確認する

無事にnonceチェックが通り、IDとパスワードも正しければ会員用トップページへ移動、そうでなければログインできないようにする

…という感じです。

ログイン処理の先頭にあるremove_filterでメールアドレスでのログインを無効化しています。
こちらの記事が大変役立ちました↓
https://xakuro.com/blog/wordpress/1287/

ほかにもfonctions.phpには処理を加えますが、分かりやすいように手順としては一旦ここで分けてご紹介します。

手順5:会員領域のページファイルに表示条件を追記する

<?php if (current_user_can('subscriber')) { ?>
<!-- 手順2の内容が入る -->

<?php else { non_member_redirect(); } ?>

current_user_canで購読者であれば内容を表示し、そうでなければnon_member_redirect関数(後述)を実行してね、という内容を追記します。

手順6:ログアウト処理用の固定ページファイルを用意する

会員用ログアウトボタンが押されたら遷移する、ログアウト処理のためだけに存在するページを作成します。
/logoutなどとスラッグを指定して、page-logout.phpを作ります。
後述する最後の手順で実行する関数を呼び出す記述だけを書いて保存しておきます。

<?php member_logout(); ?>

手順7:残りの処理をfunctions.phpに追記する

// 非ログイン時に一般用トップ画面へ遷移
function non_member_redirect()
{
  if (current_user_can('subscriber')) {
    return;
  } else {
    wp_safe_redirect(esc_url(home_url('/')));
    exit;
  }
}

// 会員用ログアウトページ用の処理
function member_logout()
{
  if (current_user_can('subscriber')) {
    wp_logout();
    wp_safe_redirect(esc_url(home_url('/')));
    exit;
  } else {
    wp_safe_redirect(esc_url(home_url('/login')));
    exit;
  }
}

// 会員アカウント(購読者)がダッシュボードにアクセスしたら、ログアウト後にトップへ戻す
add_action( 'auth_redirect', 'subscriber_go_to_home' );
function subscriber_go_to_home() {
    if ( current_user_can('subscriber') ) {
	wp_logout();
	wp_safe_redirect( esc_url( home_url( '/' )) );
	exit;
    }
}
  • 会員領域のページに会員用でログインしていない時にアクセスが試みられた際のリダイレクト処理→一般ページのトップへ移動させる
  • 会員用ログアウトボタンが押された際に呼び出されるログアウト処理
  • 購読者権限を会員用専用で使用するため、購読者はダッシュボードにアクセスできないようにログアウト→一般ページのトップへ移動させる

といった残りの処理をfunctions.phpに追記しておきます。

管理者も会員領域を閲覧できるようにする・ページの秘匿性を高める対応なども考慮していく必要があるかと思いますが、とりあえず購読者権限を活用した会員機能の実装は以上で完了するかと思います。

補足

リダイレクト処理ではwp_redirectもありますが、wp_safe_redirectは同じWordPress内での遷移用として存在するのでそちらでのコーディングとしています。

終わりに

実際に実装してみて、WordPressのユーザーの意外な活用方法を見つけることができました。
要件次第ではプラグインで実装できない内容もあるかと思いますので、今回のようなカスタマイズのアイディアで開発できないか考える機会にもなりました。

以上、何かの参考になれば幸いです!

Discussion