プラグインなしで会員のみが閲覧可能なWordPressを構築するスニペット

メンバー限定

WordPressで会員限定のサイトを作る場合、プラグインを入れるだけで構築できてしまいますが、今回は、会員限定のサイトをプラグインなしで作ってみます。

当サイトでも使っているWordPressテーマ「SANGO」をベースにして作ってみたサンプルもあるので、併せて参考にしてみてください。

実装後のサンプル

早速サンプルですが、別のURLで構築してみました。

ログイン画面
サンプルのログイン画面

サンプルは「ログイン画面」「メンバー新規登録」「登録完了後のサンクスページ」の3種類で、以下のURLを選択するとログイン画面に遷移します。

サンプルのURL https://dubdesign.net/member/

かかかず
かかかず

メンバー新規登録も可能ですが、承認制の為その後のログインはできないのでご注意ください。

仮の話ですが、メンバーで登録が完了してログインすると、通常のSANGOのブログが閲覧できるような造りです。

注意点

この記事のスニペットは、基本コピペで実装できますが functions.php をいじります。

functions.phpは色々なことができるファイルですが、いじるのをミスってしまうと、WordPress全体が真っ白のエラーになってしまうこともあるので、注意が必要です。

バックアップをとってからやりましょう。

functions.phpをいじる場合、ftpで必ずバックアップを取ってから行い、テーマ本体ではなく子テーマの方に関数をコピペするようにしましょう。

実装の手順と方法

手順と方法

それでは、実装の手順と方法です。

全部で6つのSTEPになり、行う内容も多いので順にご覧ください。

設定を確認

まずはじめに、WordPressのダッシュボードから設定を確認しておきましょう。

確認するのは、新規登録したユーザーのデフォルトの権限で、場所はメニューの「設定 > 一般」の中にある以下の2つです。

設定画面
ダッシュボード

インストール直後であれば、そのままで大丈夫ですが、上記のように「だれでもユーザー登録ができるようにする」のチェックが外れていて、新規ユーザーのデフォルト権限グループが「購読者」になっていればOKです。

かかかず
かかかず

このようになっていれば問題ありません。次のSTEPに進みましょう。

ログイン画面の作成

まずは、会員のログイン画面を作ります。

ログイン画面のUI
ログイン画面

ログイン画面は、以下3つを行って作ります。

  • functions.phpにログイン用の関数を記述
  • 固定ページに使うテンプレートファイルを作成
  • 固定ページを作成

基本コピペでOKなので、順に紹介していきます。

functions.phpにログイン用の関数を記述

まずは、ログイン用の関数をコピペします。以下のコードをfunctions.phpにコピペしましょう。

コードを表示する

functions.php

/************************
ログイン
*************************/
function my_user_login() {
    $user_name = isset( $_POST['user_name'] ) ? sanitize_text_field( $_POST['user_name'] ) : '';
    $user_pass = isset( $_POST['user_pass'] ) ? sanitize_text_field( $_POST['user_pass'] ) : '';

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

    //ログイン失敗時の処理
    if ( is_wp_error( $user ) ) {
        echo $user->get_error_message();
        exit;
    }

    //ログイン成功時の処理 
    wp_redirect( 'https://dubdesign.net/member/' );
    exit;

    return;
}

/**
 * after_setup_theme に処理をフック
 */
add_action('after_setup_theme', function() {
    if ( isset( $_POST['my_submit'] ) && $_POST['my_submit'] === 'login') {

        // nonceチェック
        if ( !isset( $_POST['my_nonce_name'] ) ) return;
        if ( !wp_verify_nonce( $_POST['my_nonce_name'], 'my_nonce_action' ) ) return;

        // ログインフォームからの送信があれば
        my_user_login();
    }
});

//ログインここまで
//

固定ページに使うテンプレートファイルを作成

次に、会員ログイン画面を作る為、固定ページのテンプレートファイルを作ります。ファイル名は「page-login.php」でファイルを作り以下のコードをコピペします。

コードを表示する

php

<?php
/*
Template Name: メンバー登録
Template Post Type: page
*/
?>
<?php 
  get_header(); 
  sng_category_query();
?>
<?php //ログインUI ?>
<div class="loginForm">
<img src="https://dubdesign.net/member/wp-content/uploads/2022/03/bluefvsp_logoonly2.svg" alt="ロゴ">
<form class="my_form" name="my_login_form" id="my_login_form" action="" method="post">
    <div class="formUsername">
		<label for="login_user_name">ユーザID</label>
        <input id="login_user_name" name="user_name" type="text" required>
    </div>
    <div class="formPassword">
        <label for="login_password">パスワード</label>
        <input id="login_password" name="user_pass" id="user_pass" type="password" required>
    </div>
    <button type="submit" name="my_submit" class="my_submit_btn" value="login">ログイン</button>
    <p class="my_forgot_pass">
        <a href="/member/wp-login.php?action=lostpassword">パスワードを忘れた方はこちらから</a>
    </p>
    <?php wp_nonce_field( 'my_nonce_action', 'my_nonce_name' );  //nonceフィールド設置 ?>
</form>
</div>
<?php //新規メンバー ?>
<div class="memberResist">
	<p>アカウントをお持ちでないですか?</p>
	<a href="/member/regist/">メンバー新規登録</a>
</div>
<?php get_footer(); ?>

ファイルができたら、有効にしているテーマ階層(wp-content > themes > 使用中のテーマ)にそのファイルをftpで設置します。

固定ページを作成

次に固定ページを作ります。新規作成で任意の名称を付け、画面右側にある「テンプレート」で、先ほど作った「ログイン」のテンプレートを選択して公開します。

ログイン
スラッグの一例
かかかず
かかかず

スラッグは、「login」のように、わかりやすい方がオススメです。

新規ユーザー登録画面を作成

次に、新規ユーザーの登録画面を作ります。

新規登録画面のUI
会員登録画面

ログイン画面は、以下3つを行って作ります。

  • functions.phpに会員登録の関数を記述
  • 固定ページに使うテンプレートファイルを作成
  • 固定ページを作成

これらもコピペでOKなので、順に紹介していきます。

functions.phpに会員登録の関数を記述

コードをfunctions.phpにコピペしましょう。このコードで、登録する項目や登録成功の条件判定を行います。

コードを表示する

functions.php

/************************
購読者で会員登録
*************************/
function my_user_signup() {
    $user_name  = isset( $_POST['user_name'] ) ? sanitize_text_field( $_POST['user_name'] ) : '';
    $user_pass  = isset( $_POST['user_pass'] ) ? sanitize_text_field( $_POST['user_pass'] ) : '';
    $user_email = isset( $_POST['user_email'] ) ? sanitize_text_field( $_POST['user_email'] ) : '';
	$display_name = isset( $_POST['display_name'] ) ? sanitize_text_field( $_POST['display_name'] ) : '';

    //空じゃないかチェック
    if ( empty( $user_name ) || empty( $user_pass ) || empty( $user_email ) || empty( $display_name ) ) {
        echo '情報が不足しています。';
        exit;
    }

    //すでにユーザー名が使われていないかチェック
    $user_id = username_exists( $user_name );
    if ( $user_id !== false ) {
        echo 'すでにユーザー名「'. $user_name .'」は登録されています';
        exit;
    }

    //すでにメールアドレスが使われていないかチェック
    $user_id = email_exists( $user_email );
    if ( $user_id !== false ) {
        echo 'すでにメールアドレス「'. $user_email .'」は登録されています';
        exit;
    }

    //問題がなければユーザーを登録する処理を開始
    $userdata = array(
        'user_login' => $user_name,       //  ログイン名
        'user_pass'  => $user_pass,       //  パスワード
        'user_email' => $user_email,      //  メールアドレス
		'display_name' => $display_name, //  表示名
	);
    $user_id = wp_insert_user( $userdata );

    // ユーザーの作成に失敗した場合
    if ( is_wp_error( $user_id ) ) {
        echo $user_id -> get_error_code(); // WP_Error() の第一引数
        echo $user_id -> get_error_message(); // WP_Error() の第二引数
        exit;
    }
	
    //登録完了ページへ
    wp_redirect( 'https://dubdesign.net/member/welcomepage/' );
    exit;

    return;
}

/**
 * after_setup_theme に処理をフック
 */
add_action('after_setup_theme', function() {

    //会員登録フォームからの送信があるかどうか
    if ( isset( $_POST['my_submit'] ) && $_POST['my_submit'] === 'signup') {

        // nonceチェック
        if ( !isset( $_POST['my_nonce_name'] ) ) return;
        if ( !wp_verify_nonce( $_POST['my_nonce_name'], 'my_nonce_action' ) ) return;

        // 登録処理を実行
        my_user_signup();
    }
});

//会員登録ここまで

固定ページに使うテンプレートファイルを作成

ここでも、会員登録用の固定ページのテンプレートファイルを作ります。ファイル名は「page-regist.php」でファイルを作り以下のコードをコピペします。

コードを表示する

php

<?php
/*
Template Name: メンバー登録
Template Post Type: page
*/
?>
<?php 
  get_header(); 
  sng_category_query();
?>
<?php //会員登録 ?>
<!-- modalOne -->
<div id="modalOne" class="modal">
   <div class="modal-content">
     <div class="modal-top">
       <span class="modal-close">×</span>
      </div>
     <div class="modal-container">
       <img class="img" src="https://dubdesign.net/wp-content/uploads/2021/11/cms.svg" alt="">
       <p>Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。</p><p>1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。</p><p>1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windowsでコンピューターの世界が広がります。1234567890Windo</p>
     </div>
   </div>
</div>
<!-- modalOne -->
<div class="loginForm" style="margin-bottom: 60px;">
<form class="my_form" name="my_signup_form" id="my_signup_form" action="" method="post">
    <div class="formUsername">
        <label for="signup_user_name">ユーザID</label>
        <input id="signup_user_name" name="user_name" type="text" required>
    </div>
    <div class="formUsername">
		<label for="signup_nickname">ニックネーム</label>
        <input id="signup_user_name" name="display_name" type="text" required>
    </div>
    <div class="formUsername">
        <label for="signup_password">パスワード</label>
        <input id="signup_password" placeholder="半角英数字8文字以上" name="user_pass" id="user_pass" type="password" required>
    </div>
    <div class="formPassword">
        <label for="signup_email">メールアドレス</label>
        <input id="signup_email" name="user_email" type="email" required>
    </div>
	<div class="contactAgree">
		<p>利用規約に同意の上、ご登録ください。<a class="modal-toggle btn-example" data-modal="modalOne">利用規約はこちら</a></p>
		<input type="checkbox" id="termCheck"  name="agree" value="agreement">
		<label for="termCheck" class="checkagree">利用規約に同意する</label>
	</div>
	<button id="submitButton" type="submit" name="my_submit" class="my_submit_btn" value="signup">メンバー登録</button>
	<p class="my_forgot_pass">
		<a href="/member/login">ログインはこちらから</a>
	</p>
	<?php wp_nonce_field( 'my_nonce_action', 'my_nonce_name' );  //nonceフィールド設置 ?>
</form>
</div>
<script>
// 同意でログインボタンON
document.addEventListener('DOMContentLoaded', function(event) {
  const targetButton = document.getElementById('submitButton');
  const triggerCheckbox = document.querySelector('input[name="agree"]');

  targetButton.disabled = true;
  targetButton.classList.add('is-inactive');

  triggerCheckbox.addEventListener('change', function() {
    if (this.checked) {
      targetButton.disabled = false;
      targetButton.classList.remove('is-inactive');
      targetButton.classList.add('is-active');
    } else {
      targetButton.disabled = true;
      targetButton.classList.remove('is-active');
      targetButton.classList.add('is-inactive');
    }
  }, false);
}, false);

/* モーダル */
const modalBtns = document.querySelectorAll(".modal-toggle");
modalBtns.forEach(function (btn) {
  btn.onclick = function () {
    var modal = btn.getAttribute('data-modal');
    document.getElementById(modal).style.display = "block";
  };
});
const closeBtns = document.querySelectorAll(".modal-close");
closeBtns.forEach(function (btn) {
  btn.onclick = function () {
    var modal = btn.closest('.modal');
    modal.style.display = "none";
  };
});

window.onclick = function (event) {
  if (event.target.className === "modal") {
    event.target.style.display = "none";
  }
};
</script>
<?php get_footer(); ?>

このファイルも、ログイン画面のテンプレートファイルと同様、有効にしているテーマ階層(wp-content > themes > 使用中のテーマ)にそのファイルをftpで設置します。

かかかず
かかかず

利用規約はモーダルです。モーダルの中身はダミーなので、任意のものに変更して利用ください。

固定ページを作成

ここでもログイン画面の時と同様、固定ページを作ります。画面右側にある「テンプレート」で、「メンバー登録」のテンプレートを選択して公開します。

会員登録
スラッグの一例
かかかず
かかかず

これも「regist」のように、わかりやすいスラッグがオススメです。

登録完了後の画面を作成

次に、新規登録完了後に表示する画面を作ります。

登録完了後の画面
WELCOME画面

登録完了後の画面は、以下2つを行って作ります。

  • 固定ページに使うテンプレートファイルを作成
  • 固定ページを作成

functions.phpはいじらずOKで、ここでは以下の手順で行います。

固定ページに使うテンプレートファイルを作成

ファイル名は「page-welcome.php」でファイルを作り、以下のコードをコピペします。

コードを表示する

php

<?php
/*
Template Name: WELCOME
Template Post Type: page
*/
?>
<?php 
  get_header(); 
  sng_category_query();
?>
<?php //WELCOME ?>
<div class="welcomePage">
	<img src="https://dubdesign.net/member/wp-content/uploads/2022/03/welcome.svg" alt="welcome">
	<p>メンバーの仮登録が完了しました。<br>メンバー承認後、登録時に入力頂いたメールアドレスに承認完了のメールが配信されます。<br>承認までお待ちください。</p>
</div>
<?php get_footer(); ?>

ここまでの固定ページファイルを作った時と同様、有効にしているテーマ階層(wp-content > themes > 使用中のテーマ)にこのファイルもftpで設置します。

固定ページを作成

ここでもログイン画面の時と同様、固定ページを作ります。画面右側にある「テンプレート」で、「WELCOME」のテンプレートを選択して公開します。

スラッグの一例
functions.phpにリダイレクトとアドミンバーの設定を記述

「ログインしてないユーザーはログインページにリダイレクト」と「アドミンバー非表示」の設定を、functions.phpに記述します。

以下がコードですが、リダイレクトの設定の記述で2行目の is_page(array('XX','XX','XX') には、上述で作った「ログイン」「新規登録」「登録完了」の固定ページ3種を指定する必要があります。

ここの「XX」の中には、固定ページIDをそれぞれ指定します。

コードを表示する

functions.php

/* ログインしてない&ログインページじゃない&場合リダイレクト */
function require_login() {
    if ( ! is_user_logged_in() && ! is_page(array('13','16','20')) ) {
        wp_redirect( 'https://dubdesign.net/member/login/' );
    }
}
add_action( 'template_redirect', 'require_login' );

// 管理バーを投稿者を除き表示
if (! current_user_can('publish_posts')){
    show_admin_bar(false);
}

このページIDを設定することで、ログインしていない人が見れるページを限定させることができます。

最後にCSSで見た目を整える。

最後にCSSで見た目を整える為、以下のコードをコピペします。

コードを表示する

CSS

/* ログインフォーム */

.loginForm {
    width: 100%;
    max-width: 500px;
    margin: 60px auto 40px;
    background: #FFF;
    padding: 30px 30px 10px;
    border-radius: 3px;
    box-shadow: 0 0 3px 0 rgb(0 0 0 / 12%), 0 1px 1px 0 rgb(0 0 0 / 11%);
    display: flex;
    flex-direction: column;
}
.loginForm img {
    display: block;
    width: 250px;
    margin: 10px auto 20px;
}
.formUsername {
    margin-bottom: 20px;
}
.formPassword {
    margin-bottom: 30px;
}
.formUsername input, .formPassword input {
    background: #FFF;
    border: solid 1px #aaa;
}
.loginForm button {
    width: 100%;
    display: block;
    background: #6bb6ff;
    line-height: 50px;
    border: none;
    color: #FFF;
    transition: 0.3s ease-in-out;
    font-weight: 600;
    overflow: hidden;
	position: relative;
}
.loginForm button:hover {
	opacity: 0.95;
}
.loginForm button:before{
content: '';
    display: block;
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: -100%;
    background-image: linear-gradient( 
130deg, rgba(255, 255, 255, 0) 25%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0) 55%);
    -webkit-transition: 0.5s;
    transition: 0.6s;
}
.loginForm button:hover:before {
    left: 100%;
}
button#submitButton.is-inactive {
    background: #ddd;
	pointer-events: none;
}

.contactAgree {
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
	margin-bottom: 10px;
}

input[type=checkbox] {
    display: none;
}
.checkagree {
    box-sizing: border-box;
    cursor: pointer;
    display: inline-block;
    padding: 5px 32px;
    position: relative;
    width: auto;
}
.checkagree::before {
    background: #fff;
    border: 1px solid #ccc;
    border-radius: 3px;
    content: '';
    display: block;
    height: 18px;
    left: 5px;
    margin-top: -10px;
    position: absolute;
    top: 50%;
    width: 18px;
}
.checkagree::after {
    border-right: 6px solid #6bb6ff;
    border-bottom: 3px solid #6bb6ff;
    content: '';
    display: block;
    height: 20px;
    left: 7px;
    margin-top: -18px;
    opacity: 0;
    position: absolute;
    top: 50%;
    transform: rotate(45deg) translate3d(0,2px,0) scale3d(.7,.7,1);
    transition: transform .2s ease-in-out, opacity .2s ease-in-out;
    width: 9px;
}
input[type=checkbox]:checked + .checkagree::before {
    border-color: #666;
}
input[type=checkbox]:checked + .checkagree::after {
    opacity: 1;
    transform: rotate(45deg) scale3d(1,1,1);
}

.modal {
  display: none;
  position: fixed;
  z-index: 8887;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgba(0, 0, 0, 0.7);
  transition: all 1s ease-in-out;
}
.modal-container .img {
    background: #f1f1f1;
    margin-bottom: 15px;
}
.modal-container p {
    margin-bottom: 10px;
}
.modal-container p:last-child {
    margin-bottom: 0;
}
.modal-content {
    background: #FFF;
    overflow-y: auto;
    padding: 20px 25px;
    width: 90%;
    max-width: 500px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    max-height: 400px;
    animation: show 0.6s linear 0s;
    filter: drop-shadow(0px 2px 6px #777);
}
.modal-top {
    display: inline-block;
    position: absolute;
    right: 5px;
    top: 5px;
}
.modal-close {
    color: #FF0000;
    text-decoration: none;
    font-size: 2rem;
    line-height: 1;
    padding: 0 8px;
}
.contactAgree p {
    display: inline-block;
    font-size: 0.8rem;
    position: relative;
	margin: 0;
}

.modal-close:hover, .modal-close:focus {
  text-decoration: none;
  cursor: pointer;
}
.modal-title {
  color: #FFF;
}
@keyframes show{
    from{
        opacity: 0;
    }
    to{
        opacity: 1;
    }
}

/* フォーム下の新規登録 */
.memberResist {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 40px;
}
.memberResist p {
    margin: 0;
}

/* WELCOME */
.welcomePage {
    width: 100%;
    max-width: 560px;
    margin: 60px auto;
    background: #FFF;
    padding: 20px 30px 30px;
    border-radius: 3px;
    box-shadow: 0 0 3px 0 rgb(0 0 0 / 12%), 0 1px 1px 0 rgb(0 0 0 / 11%);
    display: flex;
    flex-direction: column;
}
.welcomePage p {
    margin: 0;
    line-height: 1.6;
}
.welcomePage img {
    margin-bottom: 20px;
}
p.welcomeMemberName {
    margin-bottom: 15px;
}
p.welcomeMemberName span {
    font-size: 1.5rem;
    letter-spacing: 0.04rem;
    font-weight: 600;
    margin-right: 3px;
}

かかかず
かかかず

CSSは、ここまで作ったページ全てを含むCSSです。色味など全体感はSANGOに合わせて作っているので、好みに合わせてカスタマイズしてください。

プラグインで仮登録から本登録への制御

上記の手順で一応完了ですが、このままだと不特定多数の人がユーザー登録できてしまいます。

かかかず
かかかず

スパムユーザーも登録できてしまいます。

ので、当サイトでは新規登録ユーザーは「購読者」の権限で仮登録にし、それを目視で承認するか・否認するかをのシステムにしています。

この場合、以下プラグインの「New User Approve」がオススメです。

詳細は割愛しますが、英語ながらも無料で多機能なので是非合わせて使ってみてください。

さいごに

プラグインを増やしたくない、という方はこんな方法で構築してみるのはいかがでしたでしょうか?

見た目のカスタマイズはCSSベースでできてしまうので、案外作りやすいと思います。是非参考にしてみてください。

参考サイト

参考WordPressで会員登録フォームとログインフォームを自作してみる【プラグインなし】WEMO.tech
カテゴリーのイラスト

同じカテゴリの記事一覧

ボタンの影