PHPのフォームの入力値の受け取り方法について

採用はこちら

PHPでフォームの入力値を受け取るには、HTMLフォームの送信方法に応じて、主に $_GET または $_POST を使います。

検索フォームのようにURLへ条件を付けて送信する場合は $_GET、お問い合わせフォームや会員登録フォームのように入力内容を送信する場合は $_POST を使うのが一般的です。

また、ファイルアップロードを扱う場合は、$_POST ではなく $_FILES を使います。

PHPでフォームを扱う際は、単に値を受け取るだけでなく、未入力チェック、形式チェック、エスケープ処理、CSRF対策なども重要です。

フォームから送信される値はユーザーが自由に変更できるため、受け取った値をそのまま信用しないことが基本です。

目次

フォームの値を受け取る基本

name属性がPHPで受け取るキーになる

HTMLフォームの入力値をPHPで受け取るときに重要なのが、フォーム部品の name 属性です。

たとえば、次のような入力欄があるとします。

<input type="text" name="username">

この場合、PHP側では次のように受け取ります。

$username = $_POST['username'] ?? '';

PHPで使う $_POST['username']username は、HTML側の name="username" に対応しています。

注意したいのは、PHPで受け取るキーになるのは id 属性ではなく、name 属性だという点です。

<input type="text" id="username">

このように id だけを指定しても、PHP側では値を受け取れません。

フォームの入力値を送信するには、必ず name 属性を指定します。

未定義エラーを防ぐ受け取り方

フォームの値を受け取るとき、次のように書くこともできます。

$name = $_POST['name'];

しかし、この書き方では name が送信されていなかった場合に、未定義の配列キーに関する警告が出る可能性があります。

そのため、実務では次のように ?? を使って受け取るのが一般的です。

$name = $_POST['name'] ?? '';

?? はNull合体演算子と呼ばれるもので、左側の値が存在しない場合や null の場合に、右側の値を使います。

つまり、次のコードでは、$_POST['name'] が存在すればその値を使い、存在しなければ空文字を代入します。

$name = $_POST['name'] ?? '';

フォームの値を安全に受け取る基本形として、まずはこの形を覚えておくとよいでしょう。

GET送信で入力値を受け取る方法

GET送信とは

GET送信は、フォームの入力値をURLのクエリ文字列として送信する方法です。

たとえば、検索フォームではGET送信がよく使われます。

<form action="search.php" method="get">
  <input type="text" name="keyword">
  <button type="submit">検索</button>
</form>

このフォームで keyword に「PHP」と入力して送信すると、URLは次のようになります。

search.php?keyword=PHP

GET送信では、入力値がURLに表示されます。

そのため、検索条件や絞り込み条件、ページ番号など、URLとして共有したい情報に向いています。

$_GETで値を受け取る

GET送信された値は、PHP側で $_GET を使って受け取ります。

$keyword = $_GET['keyword'] ?? '';

受け取った値を画面に表示する場合は、そのまま echo するのではなく、必ずエスケープします。

function h($value) {
    return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

$keyword = $_GET['keyword'] ?? '';

echo '検索キーワード:' . h($keyword);

GET送信はURLに値が表示されるため、パスワード、個人情報、問い合わせ内容などの送信には向いていません。

POST送信で入力値を受け取る方法

POST送信とは

POST送信は、フォームの入力値をHTTPリクエストの本文として送信する方法です。

お問い合わせフォームや会員登録フォームなど、入力内容をサーバー側で処理するフォームでは、POST送信がよく使われます。

<form action="confirm.php" method="post">
  <input type="text" name="name">
  <input type="email" name="email">
  <textarea name="message"></textarea>
  <button type="submit">送信</button>
</form>

POST送信では、GET送信のように入力値がURLに表示されません。

ただし、POSTだから安全というわけではありません。

POSTで送られる値もユーザーが改ざんできます。

また、通信内容を保護するにはHTTPSが必要です。

$_POSTで値を受け取る

POST送信された値は、PHP側で $_POST を使って受け取ります。

$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
$message = $_POST['message'] ?? '';

実際には、前後の空白を取り除きたい項目では trim() を使うことが多いです。

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

名前やメールアドレスなどでは、前後の空白を削除した方が扱いやすくなります。

ただし、すべての入力項目に無条件で trim() を使うべきとは限りません。

パスワードや整形済みテキストなど、空白自体に意味がある項目では、仕様に応じて慎重に扱う必要があります。

入力値を画面に表示するときの注意点

htmlspecialchars()でエスケープする

フォームから受け取った値をHTML上に表示するときは、必ずエスケープ処理を行います。

ユーザーが入力した内容をそのまま画面に表示すると、XSSと呼ばれる脆弱性につながる可能性があります。

たとえば、ユーザーが次のような文字列を入力したとします。

<script>alert('test');</script>

この値をそのままHTMLに出力すると、ブラウザ上でJavaScriptが実行される可能性があります。

そのため、HTMLに表示するときは htmlspecialchars() を使います。

echo htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

毎回このように書くのは大変なので、関数にしておくと便利です。

function h($value) {
    return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

使うときは、次のように書きます。

echo h($name);

HTML属性値に出力するときもエスケープする

フォーム送信後に、入力済みの値をフォームへ再表示することがあります。

<input type="text" name="name" value="<?= h($name) ?>">

このように、HTML属性値に出力する場合もエスケープが必要です。

ENT_QUOTES を指定しておくことで、シングルクォートやダブルクォートも変換されるため、属性値の中でも安全に扱いやすくなります。

JavaScript内に出力する場合は別の方法を使う

htmlspecialchars() は、HTML本文やHTML属性値に出力する場合によく使います。

ただし、JavaScriptの中にPHPの値を埋め込む場合は、単純に htmlspecialchars() を使うだけでは不十分になることがあります。

JavaScript内に値を渡す場合は、json_encode() を使う方法が安全です。

<script>
const name = <?= json_encode($name, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
</script>

このように、出力先がHTMLなのか、HTML属性なのか、JavaScriptなのかによって、適切な処理を使い分けることが重要です。

フォーム送信を判定する方法

$_SERVER['REQUEST_METHOD']を使う

フォーム処理では、ページに初めてアクセスしただけなのか、フォームが送信された後なのかを判定したい場面があります。

その場合は、$_SERVER['REQUEST_METHOD'] を使います。

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // フォームが送信されたときの処理
}

このように書くことで、POST送信された場合だけ処理を実行できます。

たとえば、初回アクセス時にはエラーチェックを行わず、フォーム送信後だけバリデーションを行うことができます。

$errors = [];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($_POST['name'] ?? '');

    if ($name === '') {
        $errors[] = '名前を入力してください。';
    }
}

入力値のバリデーション

未入力チェック

フォームには、必須項目のチェックが必要です。

$errors = [];

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

if ($name === '') {
    $errors[] = '名前を入力してください。';
}

if ($email === '') {
    $errors[] = 'メールアドレスを入力してください。';
}

if ($message === '') {
    $errors[] = 'お問い合わせ内容を入力してください。';
}

エラーがある場合は、画面に表示します。

<?php if (!empty($errors)): ?>
  <ul>
    <?php foreach ($errors as $error): ?>
      <li><?= h($error) ?></li>
    <?php endforeach; ?>
  </ul>
<?php endif; ?>

エラーメッセージもHTMLに出力するため、h() でエスケープして表示します。

メールアドレスの形式チェック

メールアドレスの形式を確認する場合は、filter_var() を使います。

if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors[] = 'メールアドレスの形式が正しくありません。';
}

必須チェックと組み合わせる場合は、次のように書けます。

if ($email === '') {
    $errors[] = 'メールアドレスを入力してください。';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors[] = 'メールアドレスの形式が正しくありません。';
}

ただし、FILTER_VALIDATE_EMAIL で確認できるのは、あくまでメールアドレスの形式です。

実際に存在するメールアドレスかどうか、本人が所有しているメールアドレスかどうかまでは確認できません。

会員登録などでは、確認メールを送信して認証する方法が一般的です。

数値のチェック

フォームから送信される値は、基本的に文字列として扱われます。

たとえば、年齢を入力するフォームがあるとします。

<input type="number" name="age">

PHP側では、次のように受け取れます。

$age = $_POST['age'] ?? '';

ただし、この時点では文字列です。年齢のように0以上の整数を扱いたい場合は、ctype_digit() を使う方法があります。

$age = $_POST['age'] ?? '';

if ($age === '') {
    $errors[] = '年齢を入力してください。';
} elseif (!ctype_digit($age)) {
    $errors[] = '年齢は半角数字で入力してください。';
} else {
    $age = (int)$age;
}

ctype_digit() は、文字列がすべて数字で構成されているかを確認する関数です。

年齢や数量など、0以上の整数だけを許可したい場合に向いています。

一方で、マイナスの数値や小数を扱う場合には向いていません。

その場合は、filter_var()FILTER_VALIDATE_INTFILTER_VALIDATE_FLOAT など、目的に合った方法を使います。

入力項目ごとの受け取り方法

テキストボックスの値を受け取る

テキストボックスの値は、通常の $_POST または $_GET で受け取ります。

<input type="text" name="name">
$name = trim($_POST['name'] ?? '');

受け取った値を表示する場合は、必ずエスケープします。

echo h($name);

メールアドレス入力欄の値を受け取る

メールアドレス入力欄も、基本的にはテキストボックスと同じです。

<input type="email" name="email">
$email = trim($_POST['email'] ?? '');

HTML側で type="email" を指定しても、PHP側のチェックは必要です。

ブラウザ側のバリデーションは無効化できるため、最終的な確認はサーバー側で行います。

if ($email === '') {
    $errors[] = 'メールアドレスを入力してください。';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors[] = 'メールアドレスの形式が正しくありません。';
}

textareaの値を受け取る

お問い合わせ内容や備考など、長文を入力する場合は textarea を使います。

<textarea name="message"></textarea>

PHP側では、通常の入力欄と同じように受け取れます。

$message = trim($_POST['message'] ?? '');

HTMLに表示する場合は、エスケープします。

echo h($message);

改行を画面上にも反映したい場合は、nl2br() を使います。

echo nl2br(h($message));

nl2br() は、文字列内の改行をHTMLの <br> に変換する関数です。

ラジオボタンの値を受け取る

ラジオボタンは、選択された1つの値だけが送信されます。

<label>
  <input type="radio" name="gender" value="male"> 男性
</label>
<label>
  <input type="radio" name="gender" value="female"> 女性
</label>
<label>
  <input type="radio" name="gender" value="other"> その他
</label>

PHP側では、次のように受け取ります。

$gender = $_POST['gender'] ?? '';

ラジオボタンは、何も選択されていない場合には値が送信されません。

そのため、?? '' で初期値を入れておくと安全です。

また、想定外の値が送信されていないか確認することも重要です。

$allowedGenders = ['male', 'female', 'other'];

if ($gender === '') {
    $errors[] = '性別を選択してください。';
} elseif (!in_array($gender, $allowedGenders, true)) {
    $errors[] = '性別の値が正しくありません。';
}

HTML上に存在しない値でも、リクエストを改ざんすれば送信できるため、PHP側でも許可する値を確認します。

チェックボックスの値を受け取る

チェックボックスは、チェックされた場合だけ値が送信されます。

<label>
  <input type="checkbox" name="agree" value="1">
  利用規約に同意する
</label>

PHP側では、次のように受け取ります。

$agree = $_POST['agree'] ?? '';

同意が必要なフォームでは、次のように確認します。

if ($agree !== '1') {
    $errors[] = '利用規約に同意してください。';
}

チェックされていない場合、agree というキー自体が送信されないため、$_POST['agree'] を直接参照しないように注意しましょう。

複数チェックボックスの値を受け取る

複数のチェックボックスを配列として受け取りたい場合は、name 属性に [] を付けます。

<label>
  <input type="checkbox" name="interests[]" value="php"> PHP
</label>
<label>
  <input type="checkbox" name="interests[]" value="javascript"> JavaScript
</label>
<label>
  <input type="checkbox" name="interests[]" value="html"> HTML
</label>

PHP側では、配列として受け取ります。

$interests = $_POST['interests'] ?? [];

ただし、必ず配列で送信されるとは限りません。

リクエストを改ざんされる可能性もあるため、配列かどうかを確認します。

$interests = $_POST['interests'] ?? [];

if (!is_array($interests)) {
    $interests = [];
}

さらに、想定された値だけを許可します。

$allowedInterests = ['php', 'javascript', 'html'];

foreach ($interests as $interest) {
    if (!in_array($interest, $allowedInterests, true)) {
        $errors[] = '興味のある分野の値が正しくありません。';
        break;
    }
}

セレクトボックスの値を受け取る

セレクトボックスでは、選択された値が送信されます。

<select name="prefecture">
  <option value="">選択してください</option>
  <option value="tokyo">東京都</option>
  <option value="osaka">大阪府</option>
  <option value="okayama">岡山県</option>
</select>

PHP側では、次のように受け取ります。

$prefecture = $_POST['prefecture'] ?? '';

セレクトボックスでも、想定外の値が送信されていないか確認します。

$allowedPrefectures = ['tokyo', 'osaka', 'okayama'];

if ($prefecture === '') {
    $errors[] = '都道府県を選択してください。';
} elseif (!in_array($prefecture, $allowedPrefectures, true)) {
    $errors[] = '都道府県の値が正しくありません。';
}

hiddenの値を受け取る

hiddenは、画面には表示されない値を送信したいときに使います。

<input type="hidden" name="product_id" value="123">

PHP側では、次のように受け取ります。

$productId = $_POST['product_id'] ?? '';

ただし、hiddenの値はユーザーに見えないだけで、改ざんは可能です。

そのため、価格、権限、ユーザーID、割引率、管理者フラグなどの重要な値をhiddenだけに頼ってはいけません。

たとえば、次のように商品の価格をhiddenで送るのは危険です。

<input type="hidden" name="price" value="10000">

ユーザーがこの値を変更して送信する可能性があるためです。

価格や権限などの重要情報は、送信された値をそのまま信用せず、サーバー側のデータベースやセッションを基準に確認します。

ファイルアップロードの値を受け取る方法

ファイルアップロードでは$_FILESを使う

ファイルアップロードの場合は、$_POST ではなく $_FILES を使います。

HTMLフォームでは、method="post" に加えて、enctype="multipart/form-data" を指定する必要があります。

<form action="upload.php" method="post" enctype="multipart/form-data">
  <input type="file" name="upload_file">
  <button type="submit">アップロード</button>
</form>

PHP側では、次のように受け取ります。

$file = $_FILES['upload_file'] ?? null;

アップロードされたファイルの情報は、次のように取得できます。

$name = $_FILES['upload_file']['name'];
$type = $_FILES['upload_file']['type'];
$tmpName = $_FILES['upload_file']['tmp_name'];
$error = $_FILES['upload_file']['error'];
$size = $_FILES['upload_file']['size'];

アップロードエラーを確認する

ファイルアップロードでは、まずエラーの有無を確認します。

if ($_FILES['upload_file']['error'] !== UPLOAD_ERR_OK) {
    $errors[] = 'ファイルアップロードに失敗しました。';
}

ファイルが正常にアップロードされていない状態で保存処理を行うと、不具合やセキュリティリスクにつながる可能性があります。

move_uploaded_file()で保存する

アップロードされたファイルを保存する場合は、move_uploaded_file() を使います。

$tmpName = $_FILES['upload_file']['tmp_name'];
$savePath = __DIR__ . '/uploads/sample.jpg';

if (!move_uploaded_file($tmpName, $savePath)) {
    $errors[] = 'ファイルの保存に失敗しました。';
}

move_uploaded_file() は、アップロードされた一時ファイルを指定した場所へ移動するための関数です。

実務では、元のファイル名をそのまま保存名に使わず、ランダムなファイル名を生成するのが一般的です。

ファイルアップロードで注意すべきこと

ファイルアップロードは、通常のテキストフォームよりも慎重に扱う必要があります。

特に、以下の点に注意します。

・ファイルサイズを制限する
・許可する拡張子を限定する
・MIMEタイプを確認する
・元のファイル名をそのまま使わない
・保存ファイル名をランダムにする
・アップロード先のディレクトリを適切に管理する
・PHPファイルなどの実行可能ファイルをアップロードさせない
・画像の場合でも本当に画像かどうか確認する

また、PHPの設定である post_max_sizeupload_max_filesize を超えると、$_POST$_FILES が空になることがあります。

大きなファイルを扱う場合は、PHPの設定値も確認しておく必要があります。

filter_input()を使って受け取る方法

filter_input()の基本

PHPでは、$_POST$_GET を直接参照する代わりに、filter_input() を使って値を受け取ることもできます。

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

INPUT_POST を指定するとPOST送信された値を、INPUT_GET を指定するとGET送信された値を取得できます。

$keyword = filter_input(INPUT_GET, 'keyword');

filter_input()の注意点

filter_input() は便利ですが、使えば自動的に安全になるわけではありません。

第3引数にフィルタを指定しない場合、基本的には値をそのまま取得するだけです。

メールアドレスの形式を確認したい場合は、次のようにフィルタを明示します。

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

ただし、存在しない場合は null、バリデーションに失敗した場合は false になることがあります。

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

if ($email === null || $email === false) {
    $errors[] = 'メールアドレスの形式が正しくありません。';
}

初心者の場合は、まず $_POST$_GET で受け取り、必要に応じて trim()filter_var()、エスケープ処理を行う形から覚えると理解しやすいでしょう。

$_REQUESTは基本的に使わない

$_REQUESTとは

PHPには、$_REQUEST というスーパーグローバル変数もあります。

$value = $_REQUEST['name'] ?? '';

$_REQUEST には、$_GET$_POST$_COOKIE などの値が含まれます。

一見便利に見えますが、どこから送られた値なのかが分かりにくくなります。

$_GET$_POSTを明示的に使い分ける

フォームの値を受け取る場合は、送信方法に合わせて $_GET または $_POST を明示的に使うのが基本です。

$keyword = $_GET['keyword'] ?? '';
$name = $_POST['name'] ?? '';

$_REQUEST を使うと、GETで送られた値なのか、POSTで送られた値なのか、Cookie由来の値なのかが分かりにくくなります。

そのため、実務では基本的に $_REQUEST は避け、目的に応じて $_GET$_POST$_COOKIE を使い分けます。

入力画面と処理を同じファイルに書く例

基本的なフォーム処理のサンプル

小規模なフォームでは、入力画面と処理を同じPHPファイルに書くことがあります。

以下は、お問い合わせフォームの基本例です。

<?php
function h($value) {
    return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

$errors = [];

$name = '';
$email = '';
$message = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($_POST['name'] ?? '');
    $email = trim($_POST['email'] ?? '');
    $message = trim($_POST['message'] ?? '');

    if ($name === '') {
        $errors[] = '名前を入力してください。';
    }

    if ($email === '') {
        $errors[] = 'メールアドレスを入力してください。';
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = 'メールアドレスの形式が正しくありません。';
    }

    if ($message === '') {
        $errors[] = 'お問い合わせ内容を入力してください。';
    }

    if (empty($errors)) {
        header('Location: complete.php');
        exit;
    }
}
?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>お問い合わせフォーム</title>
</head>
<body>

<h1>お問い合わせ</h1>

<?php if (!empty($errors)): ?>
  <ul>
    <?php foreach ($errors as $error): ?>
      <li><?= h($error) ?></li>
    <?php endforeach; ?>
  </ul>
<?php endif; ?>

<form action="index.php" method="post">
  <p>
    <label>
      名前<br>
      <input type="text" name="name" value="<?= h($name) ?>">
    </label>
  </p>

  <p>
    <label>
      メールアドレス<br>
      <input type="email" name="email" value="<?= h($email) ?>">
    </label>
  </p>

  <p>
    <label>
      お問い合わせ内容<br>
      <textarea name="message"><?= h($message) ?></textarea>
    </label>
  </p>

  <button type="submit">送信</button>
</form>

</body>
</html>

入力値を再表示する理由

このコードでは、エラーがあった場合に、入力済みの値をフォームに再表示しています。

<input type="text" name="name" value="<?= h($name) ?>">

これにより、ユーザーはエラーが出たあとに最初から入力し直す必要がなくなります。

ただし、再表示するときも、必ず h() でエスケープします。

確認画面を作る場合の受け取り方

入力画面から確認画面へ送信する

お問い合わせフォームでは、次のような流れにすることがあります。

入力画面 → 確認画面 → 完了画面

入力画面では、確認画面へPOST送信します。

<form action="confirm.php" method="post">
  <input type="text" name="name">
  <input type="email" name="email">
  <textarea name="message"></textarea>
  <button type="submit">確認する</button>
</form>

確認画面で値を受け取る

確認画面では、POSTされた値を受け取って表示します。

<?php
function h($value) {
    return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
?>

<p>名前:<?= h($name) ?></p>
<p>メールアドレス:<?= h($email) ?></p>
<p>お問い合わせ内容:<?= nl2br(h($message)) ?></p>

確認画面から完了画面へ値を渡す場合は、hiddenを使う方法があります。

<form action="complete.php" method="post">
  <input type="hidden" name="name" value="<?= h($name) ?>">
  <input type="hidden" name="email" value="<?= h($email) ?>">
  <input type="hidden" name="message" value="<?= h($message) ?>">

  <button type="submit">送信する</button>
</form>

ただし、hiddenの値は改ざんできるため、完了画面でも再度バリデーションする必要があります。

より安全に管理したい場合は、確認画面でセッションに値を保存し、完了画面でセッションから取り出す方法もあります。

CSRF対策も重要

CSRFとは

CSRFとは、ユーザーが意図しないリクエストを外部サイトなどから送信させられる攻撃のことです。

お問い合わせフォームのような単純な送信でも注意は必要ですが、特に以下のような処理ではCSRF対策が重要です。

・会員情報の変更
・パスワード変更
・メールアドレス変更
・商品購入
・投稿、編集、削除
・退会処理
・管理画面での更新処理

CSRFトークンを使う

CSRF対策では、セッションにトークンを保存し、フォーム送信時にそのトークンが一致するか確認する方法がよく使われます。

まず、セッションを開始してトークンを作成します。

session_start();

if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

フォームには、hiddenでトークンを埋め込みます。

<input type="hidden" name="csrf_token" value="<?= h($_SESSION['csrf_token']) ?>">

送信後に、セッションのトークンとPOSTされたトークンを照合します。

$csrfToken = $_POST['csrf_token'] ?? '';

if (
    empty($_SESSION['csrf_token']) ||
    !hash_equals($_SESSION['csrf_token'], $csrfToken)
) {
    exit('不正なリクエストです。');
}

hash_equals() を使うことで、安全に文字列を比較できます。

データベースに保存するときの注意点

入力値をSQLに直接連結しない

フォームの入力値をデータベースに保存する場合、SQL文に直接連結してはいけません。

悪い例は次のような書き方です。

$sql = "INSERT INTO users (name) VALUES ('$name')";

このような書き方は、SQLインジェクションの原因になります。

プリペアドステートメントを使う

データベースに保存する場合は、PDOのプリペアドステートメントを使います。

$stmt = $pdo->prepare('INSERT INTO users (name) VALUES (:name)');
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();

プレースホルダを使うことで、入力値をSQL文とは別の値として扱えます。

ただし、テーブル名やカラム名はプレースホルダにできません。

ユーザー入力からテーブル名やカラム名を直接組み立てないように注意しましょう。

POST送信後はリダイレクトする

二重送信を防ぐ

POST送信後にそのまま完了メッセージを表示すると、ブラウザを更新したときにフォームが再送信されることがあります。

これを防ぐために、処理が完了したら完了ページへリダイレクトするのが一般的です。

if (empty($errors)) {
    // 保存処理やメール送信処理

    header('Location: complete.php');
    exit;
}

PRGパターンとは

POST送信後にリダイレクトする考え方を、PRGパターンと呼びます。

PRGは、Post/Redirect/Getの略です。

POSTで送信
↓
サーバー側で処理
↓
完了ページへリダイレクト
↓
GETで完了ページを表示

この流れにすることで、ページ更新による二重送信を防ぎやすくなります。

お問い合わせフォームや注文フォームなどでは、PRGパターンを使うと安全です。

よくあるミス

name属性を書いていない

フォームの値をPHPで受け取るには、name 属性が必要です。

<input type="text" id="name">

このように id だけを書いても、PHPでは値を受け取れません。

正しくは、次のように name 属性を指定します。

<input type="text" name="name" id="name">

methodと受け取り側が一致していない

HTMLフォームで method="post" を指定している場合は、PHP側では $_POST を使います。

<form method="post">
$name = $_POST['name'] ?? '';

一方、method="get" を指定している場合は、PHP側では $_GET を使います。

<form method="get">
$keyword = $_GET['keyword'] ?? '';

送信方法と受け取り方法が一致していないと、値を取得できません。

actionの送信先が間違っている

フォームの送信先は action 属性で指定します。

<form action="confirm.php" method="post">

この場合、フォームの値は confirm.php に送信されます。

別のPHPファイルで値を受け取ろうとしても、そのファイルに送信されていなければ値は取得できません。

同じファイルに送信する場合は、ファイル名を明示すると分かりやすいです。

<form action="index.php" method="post">

action="" と書く方法もありますが、現在のURLに送信されるため、初心者の場合は送信先を明示した方が分かりやすいでしょう。

チェックボックス未選択時の扱いを忘れる

チェックボックスは、チェックされていない場合、値が送信されません。

そのため、次のように直接参照すると、未定義の配列キーに関する警告が出る可能性があります。

$agree = $_POST['agree'];

安全に受け取るには、次のように書きます。

$agree = $_POST['agree'] ?? '';

hiddenの値を信用してしまう

hiddenは画面に表示されないだけで、値は変更できます。

そのため、hiddenで送られてきた価格や権限などを、そのまま信用してはいけません。

重要な情報は、サーバー側のデータベースやセッションを使って確認します。

入力値をそのまま画面に表示する

フォームから送られた値を、そのまま画面に表示するのは危険です。

echo $_POST['name'];

このような書き方は避け、必ずエスケープして表示します。

echo h($_POST['name'] ?? '');

入力値をそのままSQLに入れる

フォームの値をSQLに直接連結すると、SQLインジェクションの原因になります。

$sql = "INSERT INTO users (name) VALUES ('$name')";

データベースに保存する場合は、プリペアドステートメントを使います。

$stmt = $pdo->prepare('INSERT INTO users (name) VALUES (:name)');
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();

PHPフォーム処理の基本的な流れ

送信から完了までの流れ

PHPでフォームを扱う場合、基本的には次の流れで処理します。

1. フォームが送信されたか確認する
2. $_GET または $_POST で値を受け取る
3. 必要に応じて trim() で前後の空白を削除する
4. 必須チェックを行う
5. メールアドレスや数値などの形式チェックを行う
6. ラジオボタンやセレクトボックスは想定値か確認する
7. 画面に表示するときはエスケープする
8. データベース保存時はプリペアドステートメントを使う
9. 必要に応じてCSRF対策を行う
10. 処理完了後はリダイレクトする

重要なのは、フォームから送信された値を信用しないことです。

HTML側で requiredtype="email" を指定していても、PHP側で必ずチェックする必要があります。

ブラウザの入力チェックはユーザー側で無効化できるため、最終的な検証はサーバー側で行います。

まとめ

PHPでフォームの値を受け取る基本

PHPでフォームの入力値を受け取る基本は、送信方法に応じて使い分けることです。

GET送信の場合は、$_GET を使います。

$keyword = $_GET['keyword'] ?? '';

POST送信の場合は、$_POST を使います。

$name = $_POST['name'] ?? '';

ファイルアップロードの場合は、$_FILES を使います。

$file = $_FILES['upload_file'] ?? null;

安全に扱うことが重要

PHPのフォーム処理では、入力値を受け取るだけでなく、安全に扱うことが重要です。

特に、以下の点に注意します。

・フォーム部品にはname属性を指定する
・methodに合わせて$_GETまたは$_POSTを使う
・未定義エラーを防ぐために ?? を使う
・必要に応じてtrim()で前後の空白を削除する
・必須チェックや形式チェックを行う
・ラジオボタンやセレクトボックスは許可値を確認する
・HTMLに表示するときはhtmlspecialchars()でエスケープする
・JavaScript内に出力する場合はjson_encode()などを使う
・hiddenの値は信用しない
・ファイルアップロードはサイズ、拡張子、MIMEタイプ、保存先を確認する
・データベース保存時はプリペアドステートメントを使う
・重要な処理ではCSRF対策を行う
・POST処理後はリダイレクトして二重送信を防ぐ

最も基本的な受け取り方は、次の形です。

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

echo htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

この形を基本として、入力項目の種類に応じてバリデーションやエスケープ処理を追加していくと、安全で扱いやすいフォーム処理を作ることができます。

以上、PHPのフォームの入力値の受け取り方法についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次