PHPフォームの確認画面

確認画面をPHPとHTMLで作成

form.phpのHTML/CSS作成後、確認画面のPHPを作成します。php-contact/ フォルダの中にconfirm.phpを作成します。

confirm.php PHPのコードを作成

入力フォームから確認ボタンをクリックしたあと、別のページで送信された内容を一旦確認し、間違いがあったら修正するボタンをクリックして、入力フォーム画面に戻ります。

<?php
// エスケープ関数(ファイル内に定義)
function h($str)
{
    return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}
// ==========================
// 入力値の初期化(重要ポイント)
// ==========================
// フォームからの値が送信されない(未入力)場合でもエラーにならないよう、
// すべての変数をあらかじめ空で初期化しておきます。
// PHPは未定義の変数を使うと Warning が出るため、安全な書き方です。

$name = '';
$email = '';
$tel = '';
$message = '';
$gender = ''; 
$agree = '';
$company = ''; // (ハニーポット)

// POSTチェック
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Location: form.php');
    exit;
}

// 値を取得(null合体演算子で省略)
$name    = trim($_POST['name'] ?? '');
$email   = trim($_POST['email'] ?? '');
$tel     = trim($_POST['tel'] ?? '');
$message = trim($_POST['message'] ?? '');
$gender  = $_POST['gender'] ?? '';
$agree   = $_POST['agree'] ?? '';
$company = $_POST['company'] ?? '';


$errors = [];

//必須チェックのバリデーション
if ($name === '') {
    $errors[] = 'お名前を入力してください。';
}
if ($email === '') {
    $errors[] = 'メールアドレスを入力してください。';
}
if ($message === '') {
    $errors[] = 'お問い合わせ内容を入力してください。';
}

// メール形式チェック(空でなければ)
if ($email !== '' && !preg_match('/^[^@\s]+@[^@\s]+\.[^@\s]+$/', $email)) {
    $errors[] = 'メールアドレスの形式が正しくありません。';
}

// 電話番号(任意だが形式だけチェック)
if ($tel !== '' && !preg_match('/^[0-9\s\-()+]{9,}$/', $tel)) {
    $errors[] = '電話番号の形式が正しくありません。';
}

// 性別(任意のままでもOKなら省略。必須にしたい場合↓)
// if ($gender === '') {
//     $errors[] = '性別を選択してください。';
// }

// 同意(必須)
if ($agree !== '1') {
    $errors[] = '個人情報の取り扱いに同意してください。';
}
if ($company !== '') {
    $errors[] = '送信に失敗しました。もう一度お試しください。';
}
?>

1) 不正アクセス防止(直リンク対策)

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Location: form.php'); exit;
}
  • $_SERVER['REQUEST_METHOD'] は「GET」「POST」などのアクセス方法を表す。
  • POST送信以外(例:URL直打ち)でこの画面に来たら、form.php に戻して処理を終了する。
  • セキュリティ対策としてとても重要。

2) 変数を空文字で初期化する理由

$name = '';
$email = '';
$tel = '';
$message = '';
$gender = ''; 
$agree = '';
$company = ''; // (ハニーポット)

  • エラー防止のため:PHPでは、存在しない変数を使うと「未定義エラー」になる。
  • あらかじめ空文字で用意しておくことで、あとから安心して使える。

3) 入力値の取得(null合体演算子)

$name    = trim($_POST['name'] ?? '');
$email   = trim($_POST['email'] ?? '');
$tel     = trim($_POST['tel'] ?? '');
$message = trim($_POST['message'] ?? '');
$gender  = $_POST['gender'] ?? '';
$agree   = $_POST['agree'] ?? '';
$company = $_POST['company'] ?? '';
  • ??(null合体演算子)を使うことで「POSTで送られてきた値があれば使う、なければ空文字」という省略記法になる。
  • 例:$_POST['name'] ?? ''$_POST['name'] があれば使う、なければ ''
  • trim()を使って前後の空白を取る(チェックボックス・ラジオボタンにはつけなくても良い)

??(null合体演算子)の使い方

$name = trim($_POST[‘name’] ?? ”);

このコードでは、フォームから送られてきた「名前」の値を取得しています。
ただし、POSTで送られていない場合(未定義)は空文字にしたい、という目的です。

従来のif文を使って書くと・・・

if (isset($_POST['name'])) {
    $name = trim($_POST['name']);
} else {
    $name = '';
}

  • $_POST['name'] がセットされていれば(isset)→ その値を使う
  • そうでなければ(未送信や空)→ 空文字 '' を使う
  • trim()前後の空白も取り除いている

上記が少し進化して、isset() + 三項演算子を使った省略形

同じことを1行で書く省略形

$name = isset($_POST['name']) ? trim($_POST['name']) : '';
  • isset($_POST['name']) が true のとき → trim($_POST['name']) を使う
  • false のとき → ''(空文字)を使う
  • ?: は「三項演算子」と呼ばれ、if文を短く書くための記法

さらに進化した null合体演算子(??)を使った書き方(PHP7以降)

PHP7からは、さらにスッキリ書けるようになりました。

$name = trim($_POST['name'] ?? '');
  • ?? は「null合体演算子」と呼ばれます
  • $_POST['name']存在し、かつ null でなければ それを使う
  • 存在しなければ '' を使う
  • 三項演算子+isset の省略形として非常に使いやすい

4) バリデーション(入力チェック)

  • 必須チェック → 空かどうか
  • メール形式 → xxx@yyy.zzz 形式か
  • 電話番号 → 数字や記号だけ・9文字以上
  • 同意チェック → value="1" があるか
if ($name === '') {
    $errors[] = 'お名前を入力してください。';
}
if ($email === '') {
    $errors[] = 'メールアドレスを入力してください。';
}
if ($message === '') {
    $errors[] = 'お問い合わせ内容を入力してください。';
}

if ($email !== '' && !preg_match('/^[^@\s]+@[^@\s]+\.[^@\s]+$/', $email)) {
    $errors[] = 'メールアドレスの形式が正しくありません。';
}

if ($tel !== '' && !preg_match('/^[0-9\s\-()+]{9,}$/', $tel)) {
    $errors[] = '電話番号の形式が正しくありません。';
}

if ($agree !== '1') {
    $errors[] = '個人情報の取り扱いに同意してください。';
}
// ハニーポット(ロボット投稿対策)
if ($company !== '') {
    $errors[] = '送信に失敗しました。もう一度お試しください。';
}
  • preg_match() を使って形式チェック。
  • メールは「@と.を含む形式」、電話番号は「数字や記号で9文字以上」。
  • チェックボックスは「チェックされなければ $_POST['agree'] が送られてこない(未定義になる)」ため、
    value="1" にしておけば、同意されたときだけ '1' が送られてくるという仕組みです。

メールアドレスの正規表現の意味

  • $ → 文字列の末尾
  • / ... / → 正規表現パターン
  • ^ → 文字列の先頭
  • [^@\s]+ → 「@ と空白以外の文字」が1文字以上
  • @ → アットマークが必ず1つ
  • [^@\s]+ → その後「@ と空白以外の文字」が1文字以上
  • \. → ドット(. は特別な記号なので \. と書く)
  • [^@\s]+ → 「@ と空白以外の文字」が1文字以上

電話番号の正規表現の意味

  • ^ → 文字列の先頭
  • [0-9\s\-()+] → 使える文字の種類を指定
    • 0-9 → 数字
    • \s → 空白(スペースやタブ)
    • \- → ハイフン -
    • () → カッコ
    • + → プラス記号
  • {9,} → 上記の文字が 9文字以上
  • $ → 文字列の末尾

5) エラーの扱い(配列でまとめる)

$errors = []; // 最初に空の配列を作っておく

// 条件に合わなかったら、エラーメッセージを配列に追加していく
if ($name === '') {
    $errors[] = 'お名前を入力してください。';
}
  • こうして貯めておけば、画面に一括表示できる。
  • エラーがあるときは送信ボタンを無効化して「戻る」だけ表示

PHPの下にエラー表示と確認画面

PHPとHTMLと追加CSSのコードを作成

上記のPHP入力が終わったら、下記の表示部分であるHTMLにPHPでエラーを組み込んだり、送信された名前やメールアドレスが表示するようにします。

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>内容の確認</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
</head>

<body class="confirm">
    <main class="container">
        <h1>お問い合わせ内容の確認</h1>

        <?php if (!empty($errors)) : ?>
            <div class="errors">
                <p>以下の内容を修正してください:</p>
                <ul>
                    <?php foreach ($errors as $error): ?>
                        <li><?= h($error) ?></li>
                    <?php endforeach; ?>
                </ul>
            </div>
            <div class="actions">
                <button type="button" onclick="history.back()">戻って修正する</button>
            </div>
        <?php else: ?>
            <p>以下の内容でよろしければ「送信する」を押してください。</p>

            <form action="send.php" method="post">
                <div class="form-row">
                    <label>お名前</label>
                    <p><?= h($name) ?></p>
                    <input type="hidden" name="name" value="<?= h($name) ?>">
                </div>

                <div class="form-row">
                    <label>メールアドレス</label>
                    <p><?= h($email) ?></p>
                    <input type="hidden" name="email" value="<?= h($email) ?>">
                </div>

                <div class="form-row">
                    <label>電話番号</label>
                    <p><?= h($tel) ?></p>
                    <input type="hidden" name="tel" value="<?= h($tel) ?>">
                </div>

                <div class="form-row">
                    <label>性別</label>
                    <p><?= h($gender) ?></p>
                    <input type="hidden" name="gender" value="<?= h($gender) ?>">
                </div>

                <div class="form-row">
                    <label>お問い合わせ内容</label>
                    <p><?= nl2br(h($message)) ?></p>
                    <input type="hidden" name="message" value="<?= h($message) ?>">
                </div>

                <div class="actions">
                    <button type="button" onclick="history.back()">&lt;&lt; 修正する</button>
                    <button type="submit">送信する &gt;&gt;</button>
                </div>
            </form>
        <?php endif; ?>
    </main>
</body>

</html>

onclick="history.back()" とは?

このコードは、**「前のページに戻る」**というブラウザの履歴機能を使った処理です。
ユーザーが「戻って修正する」ボタンをクリックすると、JavaScriptの history.back() 関数によって、前のフォーム入力ページに戻ります。

<button type="button" onclick="history.back()">戻って修正する</button>
  • type="button" は、「送信ボタンではないただのボタン」であることを示しています(submitではない)。
  • onclick="..." は「クリックしたときに実行するJavaScript」を記述します。
  • history.back() は「ブラウザの1つ前のページに戻る」動作をします(戻るボタンと同じ)。
  • 戻るのは「ブラウザの履歴」なので、「form.php」に確実に戻るとは限らないこともあります(例:ブックマークから直接来た場合など)。
  • より安全に戻りたい場合は、<a href="form.php">戻る</a> というリンク形式にするのも1つの方法です。

style.cssに下記のCSSを追加しておきましょう。

/* cofirm追加css */
.confirm .form-row{
    border: 1px solid #ddd;
    display: grid;
    grid-template-columns: 1fr 2fr;
    align-items: center;
    padding: .5rem 1rem;
    border-radius: 5px;
}


.errors {
  color: #b00020;
  background: #fff5f5;
  border: 1px solid #f3caca;
  border-radius: .5rem;
  padding: .75rem 1rem;
  margin-bottom: 1rem;
}
.errors ul {
  margin: .25rem 0 0;
  padding-left: 1.25rem;
}

エラー表示ブロックの解説(<?php if (!empty($errors)) : ?><?php else: ?>

<?php if (!empty($errors)) : ?>
  <div class="errors">
    <p>以下の内容を修正してください:</p>
    <ul>
      <?php foreach ($errors as $error): ?>
        <li><?= $error ?></li>
      <?php endforeach; ?>
    </ul>
  </div>
  <div class="actions">
    <button type="button" onclick="history.back()">戻って修正する</button>
  </div>
<?php else: ?>
  <!-- エラーが無い場合の「確認用フォーム」 -->
<?php endif; ?>
  • !empty($errors)
    $errors 配列が 空でなければ true(= 1件以上のエラーがある)。
    つまり「エラーがあるときは上の <div class="errors"> を表示」し、「エラーが無いとき」は else 側の確認画面(送信用フォーム)を表示します。
    !empty($errors)count($errors) > 0 と同じ意味合いです。
  • foreach ($errors as $error)
    $errors に入っているエラーメッセージを 1件ずつ <li> に出力
    例:$errors = ['メールが不正','電話番号が不正'];
  • <?php if (...) : ?> 〜 <?php endif; ?> の「代替構文」
    テンプレート内で読みやすくする書き方です。
    通常の波カッコ { } ではなく、:endif; / endforeach; を使っています。
    <?php if (...) { ?> ... <?php } ?> と等価)
  • 分岐の方針
    • エラーがある:エラー一覧+「戻る」だけ
    • エラーがない:入力確認の一覧表示+ hidden で値を保持 → send.php へ送信

<?=h($name); ?>

  • これは <?php echo h($name); ?>省略表記
  • 変数 $name の中身を その場に出力します。h()は、先頭にユーザー定義関数で指定しているので、htmlspecialchars()で囲まれていることになります。

<?=nl2br(h($name)); ?>

  • 変数$nameをh()HTMLタグやスクリプトなどを無害化(XSS対策)
  • そのあと、nl2br()\n<br> に変換し、改行を表示。
  • <?php h(nl2br($name));?>と逆にhが外側になると、<br>&lt;br&gt; に変換されてしまい、改行が効かなくなりますので注意しましょう。またこの構文は「表示用」であり、「入力・送信用」には不要です

確認画面で hidden を使う理由

確認画面では 表示用 <p> send.phpに送る送信用 <input type="hidden"> を両方置きます。

<p><?= $email ?></p>
<input type="hidden" name="email" value="<?= $email ?>">
  • <p>:ユーザーに確認してもらう表示用
  • hidden同じ値を send.php に渡すための保持用
  • ユーザーが確認画面で編集しない前提のため type="hidden"で表示しない
  • hidden の値は ユーザーには見えませんが、開発者ツールで確認・改ざんは可能です。
    本当に重要な値は、サーバー側で再検証するのが基本です(この場合は、send.php 側で再バリデーションするのが安全)。