【PHP】filter_input を使って、文字列、論理値、配列を受け取ってみる

PHP

PHPでのバリデーションを詳しく知らなかったので、なんかないかなと調べたらでてきたので一通り触ってみて覚えようと思います。
いろいろ簡単にできないかなと模索中。

filter_input とは

ものすごい簡単にいうと $_GET や $_POST などのグローバルな値をバリデーション混みで取得して変数にいれたり、できない場合は null にする。ちなみにバリデーションの初期値は FILTER_DEFAULT で、特にバリデートもサニタイズもしません。

マニュアルの記述

mixed filter_input ( int $type , string $variable_name [, int $filter = FILTER_DEFAULT [, mixed $options ]] )

使用方法

以下のように使う。

$title = filter_input(INPUT_POST, 'title'); 
$flag = filter_input(INPUT_POST, 'flag', FILTER_VALIDATE_BOOLEAN);

こうすることで例えば上記のように title が POST で送信されてきた場合には

  • title が空だった場合は null
  • title に値が入っている場合は $title が送信された値になる
  • flag に “1”, “true”, “on”, “yes” が入っている場合は $flag が true になる
  • flag に true が入る以外の値が送信されてきた場合は $flag が false になる

という動きになるので、以下のようなコードは排除できます。

if(isset($_POST['title'])){
  $title = $_POST['title'];
} else {
  $title = null;
}
// or
$title = isset($_POST['title']) ? $_POST['title'] : null;

POST以外

第一引数の取得できる値は以下の種類があります。

  • INPUT_GET
  • INPUT_POST
  • INPUT_COOKIE
  • INPUT_SERVER
  • INPUT_ENV

いずれの引数であっても同じようにバリデーションが可能です。Cookie なんかは簡単に書き換えられるため、セキュリティを考えると使う場所はありそうですね。それ以外に関してはフレームワークを作成する時には使うのかな。。

バリデートしたい場合

バリデーションの種類はいろいろありますが、簡単な例でいうと以下のようになります。

$number = filter_input(INPUT_POST, 'number', FILTER_VALIDATE_INT); 
// "string"
=> boolean false
// 1.2
=> boolean false
// 1
=> int 1

以下のようなバリデートの種類があります。

  • FILTER_VALIDATE_BOOLEAN
  • FILTER_VALIDATE_EMAIL
  • FILTER_VALIDATE_FLOAT
  • FILTER_VALIDATE_INT
  • FILTER_VALIDATE_IP
  • FILTER_VALIDATE_MAC
  • FILTER_VALIDATE_REGEXP
  • FILTER_VALIDATE_URL

詳細はマニュアルを確認してください。 検証フィルタ

サニタイズ

公式では除去フィルタと呼ばれています。サニタイズはその名の通り除去してくれるものですが、エスケープしてくれるものと、文字そのものを無くしてくれるものがあります。同じく簡単なものをあげると

$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_SPECIAL_CHARS); 
// $_POST["title"] = "<p>タイトル</p>"
=> string '<p>タイトル</p>'

というように事前にエンコードしてくれるようになります。
また文字そのものをなくすフィルタになるのは以下になります。

$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_STRING);
// FILTER_SANITIZE_STRING でタグを除いてくれます。以下の場合は
// $_POST["title"] = "<p>タイトル</p>"
=> string 'タイトル'

というように特に正規表現を用いなくてもタグを取り除くことができます。ただし開始タグと終了タグをしっかりと検証したい場合は正規表現で頑張る必要があります。
サニタイズは以下の種類があります。

  • FILTER_SANITIZE_EMAIL
  • FILTER_SANITIZE_ENCODED
  • FILTER_SANITIZE_NUMBER_INT
  • FILTER_SANITIZE_NUMBER_FLOAT
  • FILTER_SANITIZE_SPECIAL_CHARS
  • FILTER_SANITIZE_FULL_SPECIAL_CHARS
  • FILTER_SANITIZE_STRING
  • FILTER_SANITIZE_STRIPPED
  • FILTER_SANITIZE_URL
  • FILTER_UNSAFE_RAW

フィルタ

フィルタには前述した通り、バリデーションした上で false を返すものと、サニタイズしてくれるものがあります。どちらも共通でオプションとフラグをつけることができます。

オプションの使い方

オプションは以下のようにつけられます。

$number = filter_input(INPUT_POST, 'number', FILTER_VALIDATE_INT, [
    "options" => [
      //"default" => 10,
      "max_range" => 20,
      "min_range" => 10
      ]
    ]); 

こうすることで10以上20以下の場合にのみ true でそれ以外を false にしてくれます。ちなみに default に値を入れておくと空で POST してもその値が入るようになります。

フラグの使い方

フラグを一つだけ使いたい場合や特にオプションと一緒に配列で渡す必要がない場合は以下のようにする。

$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_BACKTICK);
// FILTER_FLAG_STRIP_BACKTICK でバッククオートを除いてくれる。以下の場合は
// $_POST["title"] = "`title`" 
=> string 'title'

公式のマニュアルをみるとちょこんとのってるけども複数使う場合は以下のように使う

$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_SPECIAL_CHARS, [
    "flags" => 
       FILTER_FLAG_STRIP_BACKTICK | FILTER_FLAG_ENCODE_HIGH
    ]);
// $_POST["title"] = "`漢字`" 
=> string '&#230;&#188;&#162;&#229;&#173;&#8212;'
// FILTER_FLAG_ENCODE_HIGH を抜いた場合
$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_SPECIAL_CHARS, [
    "flags" => 
       FILTER_FLAG_STRIP_BACKTICK
    ]);
// $_POST["title"] = "`漢字`"
=> string '漢字'

FILTER_FLAG_ENCODE_HIGH は ASCII文字 の126以下の文字以外をエンコードするということなので、当然日本語はエスケープされるようになっています。ASCII文字は このページで 確認できる通り、はっきりいうとほとんど使うことがないかと思います。
フィルタのフラグ一覧は以下のページにまとまっています。
フィルタフラグ

配列を扱う場合

配列の場合は、通常の文字列とは異なるためフラグを追加する必要があります。フラグを忘れてしまうとその値が false になってしまいます。例えば以下のような form の場合は

<form action="" method="post">
  <div class="form-check">
    <input type="checkbox" name="tags[]" value="1" class="form-check-input" id="Check_1">
    <label class="form-check-label" for="Check_1">Check_1</label>
  </div>
  <div class="form-check">
    <input type="checkbox" name="tags[]" value="2" class="form-check-input" id="Check_2">
    <label class="form-check-label" for="Check_2">Check_2</label>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>

以下のように FILTER_REQUIRE_ARRAY をオプションに追加してあげると false ではなく配列が変数に入ります。もちろん、このフラグを追加して送信されたデータが配列ではない場合は false が入ります。

$tags = filter_input(INPUT_POST, 'tags', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
=> array (size=2)
    0 => string '1' (length=1)
    1 => string '2' (length=1)

まとめ

filter_input は使い道が多そうです。ただ実用的に使うとなるとメインになるのは filter_input_array になるのかなと思います。
使い方は filter_input と同じイメージで使えるようなので、どちらから学んでも良さそうな気がしてます。
次回は filter_input_array の使い方について書いていきたいと思います。

コメント