2023.01.10

WordPressで会員登録フォームを独自に実装する方法

こんにちは、Webエンジニアのゾノ( @ozonosho )です。

今回の記事ではWordPressで会員登録フォームを独自に実装する方法を紹介します。

会員制サイトを作る場合、サイト上からユーザーが自由に会員登録できる仕組みが必要になります。

WordPressには標準で会員登録フォームが備わっていますが、一般ユーザー向けに利用するにはあまりにダサいです。しかもメールアドレスだけでは登録できずWordPress独自の項目「ユーザー名(半角英数字)」の登録が必須となっているのでお世辞にも使い勝手が良いとは言えません。

ユーザーの立場で考えると、他の固定ページ同様にヘッダーやフッターが共通化されているページ上から会員登録できたり、そのサイトに合った項目(例:性別、ニックネームなど)を入力したうえで会員登録できるほうが親切でしょう。

そんなわけで、僕の運営するいくつかのサイトでは独自に会員登録フォームを実装しています。

▽実装例

※実際の会員登録ページはこちら

独自に会員登録フォームを実装すると下記のようなメリットがあります。

会員登録フォームを独自に実装するメリット
  • ユーザー名をなくしてメールアドレスだけで登録可能にできる
  • 独自の会員項目を追加して登録できる
    (例:性別、年代、プロフィール、など)
  • 権限別に登録フォームを用意できる
    (例:スタッフ用登録ページ、ユーザー用登録ページ、など)
  • 登録後に任意のページに飛ばしたり任意の案内メールを送信できる
  • 過去に不正のあったメールアドレスやIPアドレスのユーザーの新規登録を制御できる

上記のように会員登録ページ表示~登録後までの好きなタイミングに好きなだけ処理を追加することができるので、理想とする会員登録機能を実現できます。

会員登録フォームを独自に実装する方法

会員登録機能の実装は大きく分けて下記の3段階になります。

①会員登録フォームの用意
②仮登録+本人確認メール送信
③本登録処理

①会員登録フォームの用意

最低限の要素だけ入れた会員登録フォームを用意してみます。

<form method="post">

	<label for="user_email">メールアドレス</label>
	<input type="email" id="user_email" name="user_email" required>

	<label for="user_pass">パスワード</label>
	<input type="password" id="user_pass" name="user_pass" autocomplete="new-password" required>

	<input name="action" type="hidden" value="do_regist">
	<?php wp_nonce_field('do_regist', 'token'); ?>

	<button type="submit">会員登録</button>

</form>

こんな感じでしょうか。

CSRF対策用にwp_nonce_fieldでトークンを発行します。

②仮登録+本人確認メール送信

会員登録ボタンが押された後は、まずはフォームから正しい登録情報が送信されているか検証します。

入力内容に問題無い場合は仮登録をおこない、入力されたメールアドレス宛に本人確認メールを送ります。

【重要】本人確認プロセスは必須!
会員登録機能の実装方法を紹介する記事の中にはフォームに会員情報を入力したらそのまま本登録しちゃう仕様のものがありますが、それだと他人のメアドで登録できてしまうので会員登録は絶対に本人確認プロセスを挟む必要があります。

WordPressの場合はinitやwpといったフックが用意されているので、適切なタイミングで処理を挟みましょう。

functions.phpに記述する最低限の処理例を載せてみます。

<?php

add_action('wp', function() {

	if(isset($_POST['action']) && $_POST['action'] === 'do_regist') {
		do_regist();
	}

});

//仮登録処理
function do_regist() {

	//トークン認証
	if(!isset($_POST['token']) || !wp_verify_nonce($_POST['token'], 'do_regist')) {
		return false;
	}

	$user_email = (isset($_POST['user_email'])) ? $_POST['user_email'] : '';
	$user_pass = (isset($_POST['user_pass'])) ? $_POST['user_pass'] : '';

	/*
		①入力内容のチェック
	*/

	//必須項目チェック
	if(!$user_email || !$user_pass) {
		return false;
	}

	//メールアドレス形式チェック
	if(!filter_var($user_email, FILTER_VALIDATE_EMAIL)) {
		return false;
	}

	//パスワード形式チェック(例:8文字以上)
	if(strlen($user_pass) < 8) {
		return false;
	}

	//メールアドレス存在チェック
	if(!email_exists($user_email)) {
		return false;
	}

	/*
		②仮登録
	*/

	$userdata = array(
		'user_login' => get_new_user_login(),
		'user_email' => $user_email,
		'user_pass' => $user_pass,
		'role' => 'user', //割り当てたい権限
		'user_registered' => wp_date('Y-m-d H:i:s')
		'meta_input' => array(
			'flg_temp_regist' => 1
		),
	);
	$user_id = wp_insert_user($userdata);
	if(!$user_id) {
		return false;
	}

	//本人確認メール送信
	send_mail_regist($user_id, $user_email);

}

//12桁のユーザーログインを設定して返す関数
function get_new_user_login() {
	$last_id = 1;
	$args = array(
		'number' => 1,
		'orderby' => 'ID',
		'order' => 'DESC'
	);
	$users = get_users($args);
	if($users) {
		$last_id = $users[0]->ID + 1;
	}
	$new_user_login = str_pad($last_id, 12, 0, STR_PAD_LEFT);
	//存在しないアカウント名になるまで再帰処理
	while(username_exists($new_user_login)) {
		$last_id++;
		$new_user_login = str_pad($last_id, 12, 0, STR_PAD_LEFT);
	}
	return $new_user_login;
}

//本人確認メール
function send_mail_regist($user_id, $user_email) {

	$id_ssl = openssl_encrypt($user_id, 'aes-256-ecb', file_get_contents(ABSPATH . 'ssl.key'));
	$verify_url = home_url('/verify-user?action=do_verify_user&id=') . urlencode($id_ssl);

	mb_language("ja");
	mb_internal_encoding("UTF-8");
	$subject = "【要確認】本登録URLのご案内";
	$body  = "このたびはXXXにご登録いただき、ありがとうございます。
下記の本登録URLをクリックすると本人確認ならびに本登録が完了いたします。

$verify_url";

	wp_mail($user_email, $subject, $body);

}

?>

①のとおり、まずは入力内容のチェックをおこないます。
必須項目の漏れがないか、パスワードは正しい形式か、該当メールアドレスのユーザーがすでに存在しないか、などを検証します。

上記例ではエラー時にreturn falseだけしていますが、実際にはエラー内容ごとに適切なエラーメッセージを返してあげると親切です。

検証して問題なければ②のとおり仮登録処理をおこない本人確認メールを送ります。
尚、ここではメール内リンクから飛ばす本人確認ページのスラッグを「/verify-user」としています。

仮登録処理における上記コードのポイントは以下になります。

ポイント
仮登録状態と本登録状態を分けるため、仮登録状態のユーザーにカスタムフィールド「flg_temp_regist(値は1)」を設定しています。
本人確認が完了したタイミングでカスタムフィールドを削除すればゴミデータも生まれないので僕はこの管理方法を好んで利用します。
ポイント
WordPressのユーザー登録にはユーザーログイン(user_login)の値が必須となるため、ユーザーにわざわざ入力させたくない場合はこちらで任意の値を割り当てましょう。
上記コード例ではユーザーIDをベースに12桁の数字を返す関数(例:ユーザーIDが13471なら「000000013471」を返す)を用意して利用しています。

本人確認メールにおける上記コードのポイントは以下になります。

ポイント
メール内リンクから飛んできたユーザーがどのユーザーなのか判別するため、メール内リンクにユーザーのIDを加えます。
ただし「https://xxx?id=13471」のようなURLにしてしまうと自分以外のユーザーの登録リンクを推測できてしまうため、IDを暗号化することで不正登録できないようにします。
上記コード例ではopenssl_encrypt関数を利用してユーザーIDを暗号化しています。

③本登録処理

本人確認メール送信後は、メール内リンクから飛んできたユーザーにたいして本登録処理をおこないます。

先ほど記載したとおりここでは本人確認ページのスラッグを「/verify-user」としているので、このページで検証と本登録をおこないます。

functions.phpに記述する最低限の処理例を載せてみます。

<?php

add_action('wp', function() {

	if(isset($_GET['action']) && $_GET['action'] === 'do_verify_user') {
		do_verify_user();
	}

});

//本人確認(本登録)処理
function do_verify_user() {

	//URLに渡した暗号化したユーザーIDを復元
	$user_id = (isset($_GET['id'])) ? openssl_decrypt($_GET['id'], 'aes-256-ecb', file_get_contents(ABSPATH . 'ssl.key')) : 0;

	/*
		①データの検証
	*/

	//ID&ユーザーの存在チェック
	$user = get_userdata($user_id);
	if(!$user) {
		return false;
	}

	//権限チェック(仮登録状態のユーザーかどうか)
	if(!get_user_meta($user_id, 'flg_temp_regist', true)) {
		return false;
	}

	/*
		②本登録処理+ログイン状態にする
	*/

	//仮登録ステータスを削除
	delete_user_meta($user->ID, 'flg_temp_regist');

	//ログインさせる
	wp_set_auth_cookie($user_id, true);
	wp_set_current_user($user_id);

	//旧セッションは削除する
	session_regenerate_id(true);

}

?>

①のとおり、まずはデータの検証をおこないます。
正しい本人確認リンクから飛んできたか、すでに本人確認済ではないか、などデータの整合性を検証します。

検証して問題なければ②のとおり本登録処理をおこないます。
仮登録状態をカスタムフィールド「flg_temp_regist」で管理していたので、このデータを削除するだけで本登録完了になります。

正常に本人確認できたユーザーにはそのままサイトを利用していただきたいので、上記コード例のようにログイン状態にしてあげると親切かもしれません。

これで会員登録の一連の流れが実装できました。

この記事では最低限の実装例のみ記載していますが、独自に会員登録機能を実装すれば任意のプロフィール項目を追加したり登録後に好きなページに飛ばしたり何でもできるので大変便利です。ぜひお試しください。

おわりに

以上、今回の記事ではWordPressで会員登録フォームを独自に実装する方法を紹介させていただきました。

当サイトではWordPressのカスタマイズ依頼を請け負っています。実現したい機能・要望がある方はぜひ下記ページよりご相談ください。

あなたのサイトに理想の機能を実装!WordPressカスタマイズサービス

本サービスはあなたのWordPressサイトに理想の機能を実装するサービスとなります。 どのような機能・要望でも実現可能です! Wo......

→この記事を読む