PHPで「入力→確認→完了」の1ファイル完結フォームを作る
フォームでよくある「入力画面 → 確認画面 → 完了画面」の切り替えを、1つのPHPファイルだけで実現する方法をステップごとに解説します。
完成イメージ
| 状態 | $pageFlag |
表示される画面 | 次に押すボタン |
|---|---|---|---|
| 最初にアクセス | 0 |
入力画面 | 確認する (btn_confirm) |
| 確認するを押した後 | 1 |
確認画面 | 送信する (btn_submit) |
| 送信するを押した後 | 2 |
完了画面 | (なし) |
Step 1: 画面をどう切り替えるか設計する
3つの画面(入力・確認・完了)を別ファイルに分けず、1つのファイルの中でHTMLの表示を切り替える方針にします。そのために「今どの画面を表示すべきか」を覚えておく変数を用意します。
$pageFlag = 0; // 0=入力画面, 1=確認画面, 2=完了画面
これが全体の土台になる考え方です。
Step 2: 「次にどの画面に進むか」の条件をPHPの先頭に書く
ユーザーがどのボタンを押したかによって $pageFlag の値を変えます。
// 確認画面に行く条件
if (!empty($_POST['btn_confirm'])) {
$pageFlag = 1;
}
// 完了画面に行く条件
if (!empty($_POST['btn_submit'])) {
$pageFlag = 2;
}
ポイント:$_POST['btn_confirm'] は、入力画面の「確認する」ボタン(name="btn_confirm")が押されたときだけ存在します。ボタンの name 属性と $_POST のキーが対応している、という仕組みを利用しています。
Step 3: デバッグ用に受け取ったデータを確認できるようにする(任意)
if (!empty($_POST)) {
echo ('<pre>');
var_dump($_POST);
echo ('</pre>');
}
これは本来の機能ではなく、「今 $_POST に何が入っているか」を開発中に確認するためのコードです。<pre> で囲むことで var_dump の出力が整形されて見やすくなります。
⚠️ 本番公開する際は、この部分は消す(またはコメントアウトする)のが基本です。
Step 4: HTMLの土台を書く
?>
<!DOCTYPE html>
<meta charset="utf-8">
<head></head>
<body>
ここで ?> によっていったんPHPを抜け、通常のHTMLを書けるようにしています。$pageFlag の判定はすでに済んでいるので、あとはその値に応じて表示するHTMLを切り替えるだけです。
Step 5: 入力画面($pageFlag === 0)を作る
<?php if ($pageFlag === 0): ?>
<form method="POST" action="input.php">
氏名
<input type="text" name="your_name" value="<?php if (!empty($_POST['your_name'])) { echo $_POST['your_name']; } ?>">
<br>
メールアドレス
<input type="email" name="email" value="<?php if (!empty($_POST['email'])) { echo $_POST['email']; } ?>">
<br>
<input type="submit" name="btn_confirm" value="確認する">
</form>
<?php endif; ?>
工夫されている点が2つあります。
-
action="input.php":送信先を自分自身にしている(自己送信フォーム)ので、送信後もこのファイルの中で処理が続きます。 -
value属性に$_POSTの値を入れている:確認画面から「戻る」で入力画面に戻ってきたときや、入力ミスがあったときに、さっき入力した内容を消さずに残すための処理です(これを「sticky form(入力値保持)」と呼びます)。
Step 6: 確認画面($pageFlag === 1)を作る
<?php if ($pageFlag === 1): ?>
<form method="POST" action="input.php">
氏名
<?php echo $_POST['your_name']; ?>
<br>
メールアドレス
<?php echo $_POST['email']; ?>
<br>
<input type="submit" name="back" value="戻る">
<input type="submit" name="btn_submit" value="送信する">
<input type="hidden" name="your_name" value="<?php echo $_POST['your_name']; ?>">
<input type="hidden" name="email" value="<?php echo $_POST['email']; ?>">
</form>
<?php endif; ?>
ここが一番重要なポイントです。確認画面ではただ表示するだけでなく、hidden(隠し項目)で同じ値をもう一度送信できるようにしています。
なぜかというと、HTTPの仕組み上、確認画面から「送信する」を押したときにブラウザが送るのはこのフォームの中に書かれている input の値だけだからです。画面に見えている echo $_POST['your_name']; は表示するためだけのもので、次の送信には使われません。そのため、同じ値を hidden でもう一度用意しておく必要があります。
💡 「戻る」ボタン(
name="back")は用意されていますが、現在のコードには$_POST['back']をチェックして$pageFlagを0に戻す処理がまだありません。押しても入力画面に戻れないはずなので、次に直すならここが良い改善ポイントです。
Step 7: 完了画面($pageFlag === 2)を作る
<?php if ($pageFlag === 2): ?>
送信が完了しました
<?php endif; ?>
btn_submit が押されると $pageFlag が 2 になっているので、ここが表示されます。一番シンプルな画面です。
補足:HTMLのフォーム属性と$_POSTの関係
$_POST とは
スーパーグローバル変数の1つで、PHPが自動的に用意している連想配列です。フォームが method="POST" で送信されたとき、その中身がすべてここに入ります。
対応ルール:<input> の name 属性 → $_POST のキー、入力された値 → $_POST の値
<input type="text" name="your_name" value="...">
ここに「田中太郎」と入力して送信すると、PHP側では次のようにアクセスできます。
$_POST['your_name']; // '田中太郎'
name が付いていない input はスーパーグローバル変数には入らないので注意してください。
method 属性
フォームデータをどうやって送るかを指定します。主に GET と POST の2種類です。
| GET | POST | |
|---|---|---|
| データの場所 | URLの末尾に ?key=value で付く |
リクエストの本体(見えない) |
| 受け取るPHP変数 | $_GET |
$_POST |
| データ量の上限 | 少ない(URLの長さ制限) | ほぼ無制限 |
| 用途 | 検索、ページ切り替えなど | ログイン、フォーム送信、機密情報 |
| ブックマーク・履歴 | 残る(URLに出るため) | 残らない |
今回のコードは method="POST" なので $_POST でデータを受け取っています。もし method="GET" にすると、同じ name="your_name" でも $_GET['your_name'] になり、コード中の !empty($_POST['your_name']) などがすべて動かなくなります。
action 属性
フォームを送信したとき、データをどこに送るか(送信先のURL)を指定します。
<form method="POST" action="input.php">
今回のコードでは action にこのファイル自身の名前(input.php)を指定しています。これを**自己送信フォーム(self-submitting form)**と呼びます。
-
actionを空(action="")にしても、実質同じ意味になり「今のページに送信」になります。 - 別ファイルに送りたい場合(例:確認画面を
confirm.phpとして分ける場合)は、action="confirm.php"のように指定します。
今回のコードが「1ファイルで入力・確認・完了を切り替える」設計になっているのは、action を常に自分自身に向けているからです。
type(inputのtype属性)
<input> がどんな入力欄になるかを決めます。
| type | 役割 | このコードでの使われ方 |
|---|---|---|
text |
自由なテキスト入力 | 氏名 |
email |
メール形式かブラウザが簡易チェック | メールアドレス |
submit |
送信ボタン | 「確認する」「送信する」「戻る」 |
hidden |
画面には表示されないが、値を保持して一緒に送信する | 確認画面で氏名・メールを次の送信にも持ち越す |
submitのnameが特に重要
<input type="submit" name="btn_confirm" value="確認する">
<input type="submit" name="btn_submit" value="送信する">
1つのフォームに複数の送信ボタンがあっても、押されたボタンの name だけが $_POST に入ります。これを利用して、
if (!empty($_POST['btn_confirm'])) {
$pageFlag = 1;
}
のように「どのボタンが押されたか」を判定し、画面を切り替えています。ボタンの value(表示テキスト)は判定に使われていません。
hiddenが必要な理由
確認画面($pageFlag === 1)を見ると:
氏名
<?php echo $_POST['your_name']; ?>
...
<input type="hidden" name="your_name" value="<?php echo $_POST['your_name']; ?>">
echo だけでは画面に表示されるだけで、次に送信されるデータにはなりません。ブラウザが実際に送信するのは「フォームの中にある <input> の値」だけなので、同じ値を hidden でもう一度用意しておかないと、「送信する」を押したときに氏名・メールのデータが消えてしまいます。
全体のつながり
-
method="POST"で送信 → PHPが$_POSTにデータを格納 -
<input name="...">の名前が$_POSTのキーになる -
action="input.php"で自分自身に送り返す -
type="submit"のボタンごとに違うnameを付けることで「どのボタンが押されたか」を判定 -
type="hidden"で、画面をまたいでデータを持ち越す
この5つの組み合わせで、1ファイルの中で入力→確認→完了の画面遷移が実現されています。
⚠️ このコードの改善ポイント
-
XSS対策がされていない:
echo $_POST['your_name']は入力値をそのまま出力しているため、<script>タグなどを入力されると実行されてしまいます。htmlspecialchars($_POST['your_name'], ENT_QUOTES, 'UTF-8')で囲む必要があります。 - バリデーションが一切ない:空欄でも確認画面に進めてしまいます。
-
「戻る」処理が未実装:
name="back"のボタンはあるが、判定するコードがありません。 - 完了画面への直接アクセスを防げていない:確認画面をスキップして完了扱いにする不正なPOSTを弾く仕組みがありません。
これらのセキュリティ対策(XSS対策・バリデーション・戻る処理の実装など)については、次の記事で詳しく解説します。今回はあくまで「画面遷移の骨組み」を理解することが目的でした。
全コード
今回解説した内容の完成形(全体)はこちらです。
<?php
if(!empty($_POST)){
echo ('<pre>');
var_dump($_POST);
echo ('</pre>');
}
//$_で書いてある変数をスーパーグローバル変数という php9種類
//特徴:連想配列(今回で言うとキーがyour_name、入力された値がバリューになる)
//入力、確認、完了3つのファイルで切り替えてもいい
//今回は個々にまとめて書く
$pageFlag = 0;
//確認画面に行く条件
if(!empty($_POST['btn_confirm'])){
$pageFlag = 1;
}
//完了画面に行く条件
if(!empty($_POST['btn_submit'])){
$pageFlag = 2;
}
?>
<!DOCTYPE html>
<meta charset="utf-8">
<head></head>
<body>
<!-- //入力画面 -->
<?php if($pageFlag === 0) :?>
<form method="POST" action="input.php">
氏名
<input type="text" name="your_name" value="<?php if(!empty($_POST['your_name'])) {echo $_POST['your_name'];} ?>">
<br>
メールアドレス
<input type="email" name="email" value="<?php if(!empty($_POST['email'])) {echo $_POST['email'];} ?>">
<br>
<input type="submit" name="btn_confirm" value="確認する">
<!-- <input type="checkbox" name="sports[]" value="野球">野球
<input type="checkbox" name="sports[]" value="サッカー">サッカー
<input type="checkbox" name="sports[]" value="バスケ">バスケ -->
<!-- <input type="submit" value="送信"> -->
</form>
<?php endif; ?>
<!-- //確認画面 -->
<?php if($pageFlag === 1) :?>
<form method="POST" action="input.php">
氏名
<?php echo $_POST['your_name'] ; ?>
<br>
メールアドレス
<?php echo $_POST['email'] ; ?>
<br>
<input type="submit" name="back" value="戻る">
<input type="submit" name="btn_submit" value="送信する">
<input type="hidden" name="your_name" value="<?php echo $_POST['your_name'] ; ?>">
<input type="hidden" name="email" value="<?php echo $_POST['email'] ; ?>">
<!-- //データを隠しておく -->
<!-- <input type="checkbox" name="sports[]" value="野球">野球
<input type="checkbox" name="sports[]" value="サッカー">サッカー
<input type="checkbox" name="sports[]" value="バスケ">バスケ -->
<!-- <input type="submit" value="送信"> -->
</form>
<?php endif; ?>
<!-- //完了画面 -->
<?php if($pageFlag === 2) :?>
送信が完了しました
<?php endif; ?>
</body>
</html>
次回の記事では、この全コードをベースに XSS対策・バリデーション・戻るボタンの実装 を1つずつ加えていきます。