0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PHP】「入力→確認→完了」の1ファイル完結フォームを作る

0
Posted at

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'] をチェックして $pageFlag0 に戻す処理がまだありません。押しても入力画面に戻れないはずなので、次に直すならここが良い改善ポイントです。


Step 7: 完了画面($pageFlag === 2)を作る

<?php if ($pageFlag === 2): ?>
    送信が完了しました
<?php endif; ?>

btn_submit が押されると $pageFlag2 になっているので、ここが表示されます。一番シンプルな画面です。


補足: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 属性

フォームデータをどうやって送るかを指定します。主に GETPOST の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 でもう一度用意しておかないと、「送信する」を押したときに氏名・メールのデータが消えてしまいます。

全体のつながり

  1. method="POST" で送信 → PHPが $_POST にデータを格納
  2. <input name="..."> の名前が $_POST のキーになる
  3. action="input.php" で自分自身に送り返す
  4. type="submit" のボタンごとに違う name を付けることで「どのボタンが押されたか」を判定
  5. type="hidden" で、画面をまたいでデータを持ち越す

この5つの組み合わせで、1ファイルの中で入力→確認→完了の画面遷移が実現されています。


⚠️ このコードの改善ポイント

  1. XSS対策がされていないecho $_POST['your_name'] は入力値をそのまま出力しているため、<script> タグなどを入力されると実行されてしまいます。htmlspecialchars($_POST['your_name'], ENT_QUOTES, 'UTF-8') で囲む必要があります。
  2. バリデーションが一切ない:空欄でも確認画面に進めてしまいます。
  3. 「戻る」処理が未実装name="back" のボタンはあるが、判定するコードがありません。
  4. 完了画面への直接アクセスを防げていない:確認画面をスキップして完了扱いにする不正な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つずつ加えていきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?