【PHP】第4回:フォーム処理(GET/POST)とバリデーション入門(安全な入力を扱う)|Dockerで学ぶ PHP→Laravel 実務入門

   青いPHPエレファント

この記事のゴール

第4回では「Webアプリらしい」処理を入れます。

  • フォームから値を送信できる
  • $_GET / $_POST の扱いを理解する
  • バリデーション(最低限)が書ける
  • XSSを避けた表示ができる
  • 次回の「DB保存(PDO)」に繋がる

1. まず理解しておくべきこと

PHPは

「フォーム入力を受け取り、処理し、HTMLを返す」

のが本業です。

そして実務では、フォーム処理が一番事故りやすいです。

  • 未入力
  • 想定外の文字列
  • 改ざん
  • XSS
  • 文字コード
  • バリデーション不足

今回は「最低限これだけは」というラインを固めます。

2. 今回のフォルダ構成

第3回までの構成に、フォーム用ファイルを追加します。

src/
├─ index.php
├─ add.php
└─ lib/
    ├─ functions.php
    └─ data.php

 

3. add.php(タスク追加フォーム)を作る

まずは入力画面です。

src/add.php

<?php

require_once __DIR__ . "/lib/functions.php";

$title = "";
$errors = [];

?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>タスク追加</title>
</head>
<body>

<h1>タスク追加</h1>

<form method="post" action="add.php">
  <div>
    <label>
      タスク名:
      <input type="text" name="title" value="<?= e($title) ?>">
    </label>
  </div>

  <div style="margin-top: 10px;">
    <button type="submit">追加</button>
  </div>
</form>

<p style="margin-top: 20px;">
  <a href="index.php">一覧へ戻る</a>
</p>

</body>
</html>

この時点ではまだ「入力できるだけ」です

保存は次回(第5回)でDBを使ってやります。

4. index.php にリンクを追加する

src/index.php の<h1> の下にリンクを足します。

<p><a href="add.php">+ タスクを追加</a></p>

5. POST送信を受け取る(add.phpを改造)

ここからが本題です。

src/add.php を次のように更新します。

<?php

require_once __DIR__ . "/lib/functions.php";

$title = "";
$errors = [];

if ($_SERVER["REQUEST_METHOD"] === "POST") {

    // ① 入力を受け取る
    $title = trim($_POST["title"] ?? "");

    // ② バリデーション
    if ($title === "") {
        $errors[] = "タスク名を入力してください。";
    }

    if (mb_strlen($title) > 100) {
        $errors[] = "タスク名は100文字以内で入力してください。";
    }

    // ③ OKなら次回はDB保存へ(今回は仮でメッセージ表示)
    if (empty($errors)) {
        // 本来はここでDBへINSERTする(第5回で実装)
        header("Location: index.php");
        exit;
    }
}

?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>タスク追加</title>
</head>
<body>

<h1>タスク追加</h1>

<?php if (!empty($errors)): ?>
  <ul style="color: red;">
    <?php foreach ($errors as $error): ?>
      <li><?= e($error) ?></li>
    <?php endforeach; ?>
  </ul>
<?php endif; ?>

<form method="post" action="add.php">
  <div>
    <label>
      タスク名:
      <input type="text" name="title" value="<?= e($title) ?>">
    </label>
  </div>

  <div style="margin-top: 10px;">
    <button type="submit">追加</button>
  </div>
</form>

<p style="margin-top: 20px;">
  <a href="index.php">一覧へ戻る</a>
</p>

</body>
</html>

6. ここで学ぶべき重要ポイント

 

6-1. $_SERVER[“REQUEST_METHOD”] を必ず見る

フォーム処理で最初にやるべきことはこれです。

if ($_SERVER["REQUEST_METHOD"] === "POST") {
    ...
}
  • 初回表示(GET) → フォームを表示
  • 送信(POST) → 入力を処理

という形になります。

6-2. $_POST[“title”] ?? “” は必須の書き方

$_POST["title"] ?? "" は、POST送信された title があればその値を取り出し、未送信や空(null)のときはエラーを出さずに空の文字列 “” を代入する安全な書き方です。

フォームは改ざんできます。
title がないようなデータが送信された場合、直接 $_POST[“title”] を呼ぶと「そんなキーはない」という警告(Undefined index)が出ます。
そのため、値がない場合に、後続の処理でエラーにならないよう、代わりの値(空文字 “”)をあらかじめ設定し

$_POST["title"] ?? ""

で安全に受け取ります。

6-3. trim は必須

ユーザーは「空白だけ」を入力できます。trimを使用する事で、空白だけ入力された場合に空白を取り除きます。

$title = trim($_POST["title"] ?? "");

trim()関数は、正確には前後の空白や改行を取り除く処理です。
前後の空白や改行を取り除く最大の理由は、ユーザーの入力ミスやコピペ時に混入した「見えない不要な空白」を取り除き、データの不整合やシステムエラーを防ぐためです。
スマホの変換やPCでのコピー&ペースト時、文字列の先頭や末尾に意図せず半角/全角スペースが入り込むことが多く、入力値チェックの誤作動防止やデータベースに登録・検索する際、メールアドレスやIDの末尾にスペースが残っていると、一致しているはずなのに「別の人・存在しないデータ」とみなされてエラーになる等のを防ぐため、基本的には入力に対してtrimしましょう。

6-4. バリデーションは「空」「長さ」から始める

最初に入れるべきバリデーションはこの2つです。

  • 必須チェック
  • 最大文字数

6-5. OKならリダイレクト(Post/Redirect/Get)

これを覚えておくと、実務で事故が減ります。

header("Location: index.php");
exit;

なぜ必要?

もしリダイレクトしないと、

  • 送信後にブラウザ更新すると再送信される
  • 二重登録の原因になる

7. ここでXSS対策を再確認する

今回、エラーメッセージ表示も

<li><?= e($error) ?></li>

にしています。

ユーザー入力ではなくても、表示する文字列は基本エスケープする癖が重要です。

8. GETについても理解しておく(超重要)

今回はPOSTで追加でしたが、一覧画面ではGETをよく使います。

例えば

  • index.php?status=open
  • index.php?keyword=筋トレ

のような絞り込みです。

GETとPOSTは、Webサーバーへデータを送受信する際の代表的な方式(HTTPメソッド)です。
主な違いは目的とデータの送り方で、GETはサーバーから「取得」し、POSTはサーバーへ「送信・登録」します。GETはURLにデータが露出しますが、POSTは目に見えない形でデータを送ります。

GETの受け取り例(次回以降で使う形)

 

$status = $_GET["status"] ?? "";

9. Laravelとの対応(ここが橋渡し)

今回のフォーム処理は、Laravelではこうなります。

今回のPHP Laravel
$_POST $request->input()
バリデーション FormRequest / validate()
header(“Location: …”) redirect()
e() Bladeの {{ }}

つまりLaravelは、

「この面倒な部分を安全に標準化したもの」

です。

10. 次回(第5回)でやること

いよいよDBです。

  • MariaDBをDocker Composeに追加
  • PDOで接続
  • tasksテーブル作成
  • タスク追加(INSERT)
  • タスク一覧(SELECT)
  • 簡易CRUDの完成

ここまで行くと、Laravelに進む準備が完全に整います。

まとめ

第4回では、

  • フォーム送信(POST)
  • 入力の受け取り
  • バリデーション(必須・最大文字数)
  • XSS対策
  • リダイレクト(PRG)

を整理しました。