Kodokon kodokon.com

フォーム:データの受け取りと検証

プロのようにフォームを扱いましょう。正しいHTTPメソッド、厳密な入力検証、そして安全な再表示です。

9 分 · 3 問

このレッスンを Kodokon で開く

フォームは、ユーザーとあなたのPHPコードとの最初の接点です。getメソッドはデータをURLの中(?q=pizza)に置きます。ページをブックマークしたり共有したりできるので、検索やフィルターに最適です。postメソッドはデータをリクエストのボディに乗せて運びます。リクエストが何かを変更するとき(アカウント作成、注文、削除)や、機密データを運ぶときに必須のメソッドです。PHPは受け取った値を$_GET$_POSTというスーパーグローバルに格納します。

HTML
<form action="search.php" method="get">
  <label for="q">Search</label>
  <input id="q" name="q" type="text">
  <button type="submit">Search</button>
</form>
<?php
$query = trim($_GET['q'] ?? '');

if ($query !== '') {
    echo "<p>You are searching for: " .
        htmlspecialchars($query, ENT_QUOTES) . "</p>";
}
?>
search.php:同じページ上のフォームとその処理。

プロの鉄則その一。入ってくるデータを決して信用しないこと。ユーザーは何でも送れます。あなたのフォームの外で作られた偽装された値も含めてです。filter_input()関数は、値の読み取りと検証を一度に行います。検証済みの値を返し、無効ならfalse、フィールドが存在しなければnullを返します。エラーメッセージで見分けるべき三つのケースです。

PHP
<?php

declare(strict_types=1);

$errors = [];

$email = filter_input(
    INPUT_POST,
    'email',
    FILTER_VALIDATE_EMAIL
);

$age = filter_input(
    INPUT_POST,
    'age',
    FILTER_VALIDATE_INT,
    ['options' => ['min_range' => 18, 'max_range' => 120]]
);

$name = trim((string) ($_POST['name'] ?? ''));

if ($name === '' || mb_strlen($name) > 50) {
    $errors[] = "Name required (50 characters max).";
}

if (!is_string($email)) {
    $errors[] = "Invalid email address.";
}

if (!is_int($age)) {
    $errors[] = "Invalid age (between 18 and 120).";
}

if ($errors === []) {
    echo "Registration valid.";
}
filter_input()で登録を検証する。

検証が失敗したとき、空のフォームを返してはいけません。ユーザーが入力した値("sticky"(貼り付く)フォーム)と、該当するフィールドの隣にエラーメッセージを再表示しましょう。再表示するどんな値もhtmlspecialchars()を通さなければなりません。これがタグを無害化し、スクリプトの注入を防ぐものです。

HTML
<?php
$name = trim($_POST['name'] ?? '');
$hasError = isset($_POST['name']) && $name === '';
$safeName = htmlspecialchars($name, ENT_QUOTES);
?>
<form method="post" action="">
  <label for="name">Your name</label>
  <input id="name" name="name"
    value="<?= $safeName ?>">
  <?php if ($hasError): ?>
    <p>Name is required.</p>
  <?php endif; ?>
  <button type="submit">Submit</button>
</form>
stickyフォーム:入力がエラーを生き延びる。

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. ユーザーアカウントを作成するフォームに適したHTTPメソッドはどれですか?
    • GET。データがURLの中に見えたままになるから
    • POST。リクエストがサーバーの状態を変更し、データがURLに現れてはならないから
    • どちらでも動く。好みの問題だから
  2. フィールドがまったく送られなかったとき、filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL)は何を返しますか?
    • false
    • 空の文字列
    • null
    • 例外を投げる
  3. ページに再表示する前に、なぜ値をhtmlspecialchars()に通すのですか?
    • HTMLタグを無害化し、スクリプトの注入(XSS脆弱性)を防ぐため
    • 打ち間違いを自動的に修正するため
    • 値を圧縮して表示を速くするため