確認画面を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()"><< 修正する</button>
<button type="submit">送信する >></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>が<br>に変換されてしまい、改行が効かなくなりますので注意しましょう。またこの構文は「表示用」であり、「入力・送信用」には不要です
確認画面で 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側で再バリデーションするのが安全)。
