PHPで安全に値を扱う:filter_inputの使い方と手動処理との違い

PHPでWebアプリケーションを開発する際、ユーザーからの入力値(フォームの送信値など)を安全に処理することは欠かせません。入力値を適切に検証・サニタイズせずに処理すると、XSS(クロスサイトスクリプティング)やSQLインジェクションなどのセキュリティリスクを招く恐れがあります。

PHPには、こうしたリスクを軽減するために用意された便利な関数 filter_input() があります。本記事ではその使い方と、使用しない場合にどのような処理が必要になるのかについて、具体例を交えて解説します。


filter_inputとは?

filter_input() は、スーパーグローバル変数($_GET, $_POST, $_COOKIE など)からの入力値を、安全に取得・検証・サニタイズできる関数です。

書式

filter_input(INPUT_TYPE, '変数名', フィルター定数, オプション);
  • INPUT_TYPE: INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV
  • 変数名: 取得したいパラメータ名(例:'id''email' など)
  • フィルター定数: FILTER_VALIDATE_INT, FILTER_VALIDATE_EMAIL, FILTER_SANITIZE_FULL_SPECIAL_CHARS など
  • オプション(任意): 範囲制限などを追加できる

filter_inputの使用例

1. 整数のバリデーション(GET)

$user_id = filter_input(INPUT_GET, 'user_id', FILTER_VALIDATE_INT);

if ($user_id === false || $user_id === null) {
    echo "不正なユーザーIDです。";
    exit;
}

2. メールアドレスの検証(POST)

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

if ($email === false) {
    echo "不正なメールアドレスです。";
    exit;
}

3. HTMLエスケープ(POST)

$comment = filter_input(INPUT_POST, 'comment', FILTER_SANITIZE_FULL_SPECIAL_CHARS);

4. 範囲付き整数チェック(年齢など)

$age = filter_input(
    INPUT_GET,
    'age',
    FILTER_VALIDATE_INT,
    array('options' => array('min_range' => 18, 'max_range' => 65))
);

filter_inputを使わない場合の処理(手動実装)

filter_input を使用せずに同様の安全処理を行う場合は、自分で存在確認・型チェック・サニタイズを行う必要があります。

1. 整数チェック

$user_id_raw = $_GET['user_id'] ?? null;

if ($user_id_raw === null || !is_numeric($user_id_raw) || intval($user_id_raw) != $user_id_raw) {
    echo "不正なユーザーIDです。";
    exit;
}

$user_id = intval($user_id_raw);

2. メールアドレスの検証

$email_raw = $_POST['email'] ?? null;

if ($email_raw === null || !filter_var($email_raw, FILTER_VALIDATE_EMAIL)) {
    echo "不正なメールアドレスです。";
    exit;
}

$email = $email_raw;

3. HTMLエスケープ

$comment_raw = $_POST['comment'] ?? '';
$comment = htmlspecialchars($comment_raw, ENT_QUOTES, 'UTF-8');

4. 範囲付き整数チェック

$age_raw = $_GET['age'] ?? null;

if (!is_numeric($age_raw) || intval($age_raw) < 18 || intval($age_raw) > 65) {
    echo "年齢は18歳以上65歳以下で入力してください。";
    exit;
}

$age = intval($age_raw);

比較:filter_input vs 手動処理

項目filter_input 利用手動処理
コードの簡潔さ○(1行で完結)✕(複数行が必要)
存在チェック自動的に null が返るisset() や null 合体演算子が必要
型バリデーション組み込みフィルターで対応可能is_numeric()intval() など手動処理
サニタイズフィルター定数で指定可能htmlspecialchars() などを明示的に使用
拡張性・保守性○(標準化された記法)✕(プロジェクトによって書き方が異なる)

filter_inputを使う際の注意点

  • 値が取得できなかった場合は null、バリデーションに失敗した場合は false が返るので、どちらもチェックするようにしましょう。
  • FILTER_SANITIZE_STRINGPHP 8.1以降で非推奨 です。代わりに FILTER_SANITIZE_FULL_SPECIAL_CHARS を使いましょう。
  • CSRF対策やSQLインジェクション防止には、別途適切なセキュリティ対策も必要です。

まとめ

filter_input() は、PHPで安全な入力処理を行うための強力なツールです。手動で処理するよりも、コードの可読性・安全性・保守性が格段に向上します。

特に以下のような理由から、セキュアなWeb開発において推奨される関数です。

  • 入力の取得と検証を1ステップで実行
  • 存在確認とバリデーションを明示的に処理
  • コードの記述ミス・抜け漏れを防げる

今後の開発では、ぜひ filter_input() を積極的に活用し、安全で堅牢なコードを書く習慣を身につけていきましょう。

コメント

タイトルとURLをコピーしました