PHP、第五章:会員登録システム。成功、失敗時のメッセージ、表示方法やリダイレクト

PHP

今回は、会員登録システムにおける成功・失敗時のメッセージ表示やその後のリダイレクト処理について解説します。ユーザーがフォームに誤った情報を入力した場合のエラーメッセージの表示方法や、修正を促すリダイレクト処理を具体的に説明します。

また、登録が成功した際に、次のアクションを案内する適切なメッセージやリダイレクト先を設定する方法についても取り上げます。簡潔で実用的なコード例を通じて、ユーザー体験を向上させるための実装手法を紹介します。

リダイレクトのタイミングと対応ページ

不正アクセスやリクエストのチェックエラーが発生した場合、処理をただちに停止し、適切なエラーメッセージを表示します。このようなケースではリダイレクトを行わず、システムが意図しない操作を防ぎます。

一方で、入力エラーや登録失敗が発生した場合には、エラーメッセージをセッションに保存し、ユーザーをフォームページへリダイレクトして再入力を促します。

また、登録が成功した場合には、ログインページやトップページなど、ユーザーが次のアクションを起こせる適切なページにリダイレクトします。

これらはあくまでも一例であり、具体的なリダイレクト先やエラーメッセージの処理方法は、システムの仕様や運用方針に応じて適宜調整してください。参考として、自身のプロジェクトに最適な設計を検討してください。

不正・エラー・成功時の処理

  • 不正アクセス:不正アクセスやリクエストのチェックエラーでは、リダイレクトは行わず処理を停止。
  • 入力エラー:入力エラーや登録失敗の場合は、エラーメッセージをセッションに保存してフォームページにリダイレクト。
  • 登録成功:登録成功時は、ログインページやトップページなど次のアクションに応じた場所にリダイレクト。

不正アクセス

不正アクセスが検出された場合、システムはただちに処理を停止し、簡潔なエラーメッセージを返すことで不正な操作を防ぎます。これには、CSRFトークンが無効、POSTメソッド以外のリクエストといったケースが含まれます。不正アクセスに対してリダイレクトを行う必要はなく、適切なエラーメッセージを表示するだけで十分です。

CSRFトークンが無効

<?php
// CSRFトークンの検証
if (empty($_POST['csrf_token']) || $_POST['csrf_token'] !== ($_SESSION['csrf_token'] ?? '')) {
    http_response_code(403);
    die("不正なアクセスです。");
}
PHP

POSTメソッド以外の場合

<?php
// POSTメソッド確認
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(403);
    die("不正なアクセスです。");
}
PHP

入力エラー

ユーザーが入力したデータに不備がある場合、エラーをセッションに保存し、フォームページにリダイレクトして再入力を促します。これにより、ユーザーは自身の入力内容を修正し、再度送信することができます。入力バリデーションエラーやメールアドレスの重複などが該当するケースです。ユーザーがわかりやすいエラーメッセージを受け取れるよう、明確にエラー内容を伝えることが重要です。

入力バリデーション失敗

<?php
// エラーがある場合はまとめて表示して終了
if (!empty($errors)) {
    foreach ($errors as $error) {
        echo $error . "<br>";
    }
    exit;
}



if (!empty($errors)) {
	$_SESSION['errors'] = $errors; // エラーメッセージをセッションに保存
	header('Location: register.php'); // フォームページにリダイレクト
    exit;
}
PHP

メールアドレス重複

<?php
    if ($count > 0) {
        // 重複があればロールバックして終了
        $pdo->rollBack();
        die("このメールアドレスはすでに登録されています。<br><a href='register.html'>戻る</a>");
    }
    

    
    if ($count > 0) {
        // 重複があればロールバックして終了
        $pdo->rollBack();
        //リダイレクト
        $_SESSION['errors'] = ['このメールアドレスはすでに登録されています。'];
        header('Location: register.php');
        exit;
    }
PHP

データベースエラー

<?php
try {

} catch (PDOException $e) {
    // エラー発生時はロールバック
    if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    echo "エラーが発生しました: " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
}


try {



} catch (PDOException $e) {
    // エラー発生時はロールバック
    if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    $_SESSION['errors'] = ['エラーが発生しました: ' . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8')];
    header('Location: register.php');
    exit;
}
?>
insert.php

登録成功

登録が成功した場合は、次のアクションに応じて適切なページにリダイレクトします。例えば、ログインページにリダイレクトしてログインを促したり、トップページに移動してサイトの利用を開始させたりします。成功メッセージをセッションに保存して次のページで表示することで、ユーザーに登録完了を明確に伝えることができます。これにより、スムーズなユーザー体験を提供します。

登録成功

<?php
    echo "登録が完了しました!";
    echo '<br><a href="index.html">トップに戻る</a>';

    $_SESSION['success'] = '登録が完了しました!';
    header('Location: index.html');
    exit;
insert.php

コードまとめ

<?php
session_start(); // セッションを開始

// CSRFトークンの検証
if (empty($_POST['csrf_token']) || $_POST['csrf_token'] !== ($_SESSION['csrf_token'] ?? '')) {
    http_response_code(403);
    die("不正なアクセスです。");
}

// トークンを使い捨てにする(再利用防止)
unset($_SESSION['csrf_token']);

// POSTメソッド確認
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(403);
    die("不正なアクセスです。");
}

// データベース接続情報
$host = 'localhost';
$dbname = 'member_system';
$charset = 'utf8';
$username = 'root';
$password = 'pass';

$name = $_POST['name'] ?? '';
$mail = $_POST['mail'] ?? '';
$pass = $_POST['pass'] ?? '';

// エラーメッセージを格納する配列
$errors = [];

// 名前の形式と長さを検証
if (empty($name)) {
    $errors[] = '名前を入力してください。';
} elseif (!preg_match('/^[a-zA-Z_-]{1,20}$/', $name)) {
    $errors[] = '名前はローマ字、アンダーバー、ハイフンのみで、20文字以内にしてください。';
}

// メールアドレスの形式と長さを検証
if (empty($mail)) {
    $errors[] = 'メールアドレスを入力してください。';
} elseif (!filter_var($mail, FILTER_VALIDATE_EMAIL)) {
    $errors[] = '無効なメールアドレスです。';
} elseif (strlen($mail) > 100) {
    $errors[] = 'メールアドレスは100文字以内にしてください。';
}

// パスワードの形式と長さを検証
if (empty($pass)) {
    $errors[] = 'パスワードを入力してください。';
} elseif (!preg_match('/^[a-zA-Z0-9_\-\[\]\.\!@]{8,20}$/', $pass)) {
    $errors[] = 'パスワードはローマ字、数字、アンダーバー、ハイフン、[].!@ のみで、8~20文字にしてください。';
}

// エラーがある場合はまとめて表示して終了
if (!empty($errors)) {
        $_SESSION['errors'] = $errors; // エラーメッセージをセッションに保存
        header('Location: register.php'); // フォームページにリダイレクト
    exit;
}
$pass = password_hash($pass, PASSWORD_DEFAULT);

try {
    $dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";
    $pdo = new PDO($dsn, $username, $password, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ]);

    // トランザクションを開始
    $pdo->beginTransaction();

    $checkSql = "SELECT COUNT(*) FROM users WHERE mail = ?";
    $checkStmt = $pdo->prepare($checkSql);
    $checkStmt->execute([$mail]);
    $count = $checkStmt->fetchColumn();

    if ($count > 0) {
        // 重複があればロールバックして終了
        $pdo->rollBack();
        //リダイレクト
        $_SESSION['errors'] = ['このメールアドレスはすでに登録されています。'];
        header('Location: register.php');
        exit;
    }

    $sql = "INSERT INTO users (name, mail, pass) VALUES (?, ?, ?)";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$name, $mail, $pass]);

    // トランザクションをコミット
    $pdo->commit();

    $_SESSION['success'] = '登録が完了しました!';
    header('Location: index.html');
    exit;
} catch (PDOException $e) {
    // エラー発生時はロールバック
    if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    $_SESSION['errors'] = ['エラーが発生しました: ' . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8')];
    header('Location: register.php');
    exit;
}
?>
insert.php

記事まとめ

不正アクセスやリクエストのチェックエラーの場合、処理をただちに停止し、不正な操作を防ぐことが重要です。一方で、入力エラーや登録失敗の場合には、ユーザーにエラーメッセージを適切に伝え、再入力を促すためのリダイレクト処理を行います。

現在の構成では、バリデーション処理は insert.php 側で行っています。ただし、エラーが発生した場合でも、その場で直接メッセージを出力するのではなく、register.php にリダイレクトしてエラー内容を表示するようにしています。フォームとエラーを同じ画面で見せることで、ユーザーがどこを修正すればよいかをすぐに判断でき、再入力もスムーズになります。

また、セキュリティ面でもこの方法が安全です。insert.php 内で詳細なエラーをそのまま表示してしまうと、バリデーションの条件や内部処理が外部に漏れる可能性があり、悪用されるリスクがあります。リダイレクトを挟むことで、こうした情報漏洩を防ぐことができます。次章では、実際にこの仕組みを用いて、入力チェックとエラーメッセージの表示をどのように実装するかを詳しく見ていきます。

コメント

タイトルとURLをコピーしました