4月 072014
 

PHPのフィルタについて勉強する

PHP5.2より標準搭載となった、Filter。Filterは、データの検証や除去を行ってくれます。今日はそのFilterに関してまとめてみます。(そう言いつつも3日くらいかけてこの記事書いているという・・・w)

Filterは、未知の(外部からの)データ、例えばユーザーの入力などに使う際に便利です。(公式のPHPドキュメントより)

基本的には公式のドキュメントにほとんど沿っているため、公式を見たほうがいいかもしれません。しかしながら、公式の訳し方は多少難解です。

確認環境

  • Mac Book Air
  • Apache/2.2.27
  • PHP5.4.26
  • Xdebug

または、

  • ideone

となります。なお、homebrewを使用しています。

では、関数を見て行きましょうか。

filter_has_varメソッド

bool filter_has_var(int $type, string $variable_name)
@param int $type INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENVのいずれか
@param string $variable_name 調べたい変数の名前を指定します。
@return bool 成功時にTRUE、失敗時にFALSEを返す。

filter_has_varメソッドは、指定した型の変数が存在するかどうかを調べることが出来ます。
型と書かれるため、intや、stringを考えますが、今回は、cookieやserver等となります。少しわかりにくい・・・。

基本的には$_から始まる変数(スーパーグローバル)の一部向けの機能のようです。

typeにかかれている通り、GET,POST,COOKIE,SERVER,ENVの判定が出来ます。

ソース(test.php)

<?php
if(filter_has_var(INPUT_GET, 'test'))
{
        echo("存在する<br>");
} else {
        echo("存在しない<br>");
}
?>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>filter_has_varの検証</h1>
<form method="GET">
<input type="hidden" name="test" value="テスト">
<input type="submit" value="テスト送信">
</form>

</body>
</html>

結果(http://localhost/test.php?test=1)

存在する

結果(http://localhost/test.php)

存在しない

注意点

あくまでも外部からの情報の検証に使われるため、ブラウザ上でないと動作を確認できませんでした。

issetよりは多少早いらしいですが、あまり好んで使おうとは思いませんね・・・。

filter_idメソッド

int filter_id(string $filtername)
@param $filtername 取得したいフィルタの名前
@return int|bool

filter_idメソッドはフィルタの名前からフィルタIDを返すメソッドです。

まず、このメソッドは、フィルタの名前を知っていることが前提となってます。

今回は、filter_listメソッドと呼ばれるサポートされているフィルタの一覧を返すメソッドを使用します。

array filter_list( void )

ソース

<?php
$filters = filter_list();
foreach($filters as $filter_name) {
  echo $filter_name.': '. filter_id($filter_name) . "\n";
}

結果

int: 257
boolean: 258
float: 259
validate_regexp: 272
validate_url: 273
validate_email: 274
validate_ip: 275
string: 513
stripped: 513
encoded: 514
special_chars: 515
full_special_chars: 522
unsafe_raw: 516
email: 517
url: 518
number_int: 519
number_float: 520
magic_quotes: 521
callback: 1024

このように、filter_idを使用することで、フィルタ名からフィルタのIDを知ることが出来ます。

filter_inputメソッド

mixed filter_input(int $type, string $variable_name[, int $filter = FILTER_DEFAULT [, mixed $options]])
@param int    $type INPUT_GET,INPUT_POST,INPUT_COOKIE,INPUT_SERVER,INPUT_ENVのどれか
@param string $variable_name 取得する変数の名前を指定します。
@param int    $filter 適用するフィルタのID
@param mixed  $options オプションあるいはフラグの論理和の連想配列を指定します。オプションを指定可能なフィルタの場合、この配列の"flags"キーにフラグを設定します。

指定した名前の変数を外部から受け取り、オプションでそれをフィルタリングします。

第3引数のoptions は以下のような書き方です。(filter_varより)
なお、callbackフィルタを使う場合は、コールバックのメソッド名をoptionsに指定します。

$options = array(
    'options' => array(
      'default' => 3, //フィルタに失敗した時のデフォルト値
      'min_range' => 0
    ),
    'flags' => FILTER_FLAG_ALLOW_OCTAL
);

なお、戻り値は複雑です。

  • 成功した場合は要求された変数の値が返ります。
  • フィルタリングに失敗すると、FALSEが返ります。
  • 変数variable_nameが設定されていない時は、NULLが返ります。

フラグFILTER_NULL_ON_FAILUREが設定されている場合

  • 変数が設定されていなければ、FALSEが返ります。
  • フィルタリングに失敗したら、NULLが返ります。

なお、フィルタに使用されるIDは複数存在します。
公式ドキュメントに記載されているフィルタの型→http://jp2.php.net/manual/ja/filter.filters.php

ソース(test.php)

<?php
// test変数がPOSTに存在するか
if(filter_has_var(INPUT_POST, 'test')) {
        $text = filter_input(INPUT_POST, 'test', FILTER_SANITIZE_SPECIAL_CHARS);
        var_dump($text);
}
?>
<html>
<head>
        <meta charaset="utf-8">
</head>
<body>
<form method="post">
        <label>文字列:<input type="textbox" name="test"></label>
        <input type="submit" value="送信">
</form>
</body>
</html>

結果(文字列:”‘><)

string '&#34;&#39;&#62;&#60;' (length=20)

注意点

  • FILTER_VALIDATE_URLを使用すると、a-.example.jpのようなホスト名のハイフンが末尾にあるURLは弾いてくれないようです。(教えていただきました)

filter_input_arrayメソッド

mixed filter_input_array(int $type [, mixed $definition [, bool $add_empty = true]])
@param int $type INPUT_GET,INPUT_POST,INPUT_COOKIE,INPUT_SERVER,INPUT_ENVのいずれかを指定。
@param mixed $definition 引数を定義する配列。または、フィルタ定数を表す整数値。
@param bool $add_empty 存在しないキーはNULLとして、返り値に追加をします。
@return また多いので、箇条書きとします。

このメソッドを使用すると、外部から変数を受け取り、オプションでそれらをフィルタリングすることが出来ます。
filter_inputメソッドを繰り返し呼ぶ必要がなくなるため、便利です。

第2引数のdefinitionに関して

第2引数のdefinitionの指定の仕方は複数有ります。(公式の情報は少しわかりにくいです。)

使用できるのは

  • 引数を定義する配列

    • 配列のキーには、対象となる変数名の文字列を指定します。
    • 対応する値はフィルタの定数(または対応する値)または、配列となります。
      • 配列の形式は、(‘filter’=>フィルタの定数, ‘flags’ => フィルタを適用するフラグ, ‘options’=>フィルタに適用するオプション)となってます。
  • フィルタの定数または、それに対応する値

    • この場合、入力配列すべてに対して、フィルタ処理がされます。

戻り値に関して

戻り値は複数有ります。

  • 成功時には、要求された変数の値を含む配列を返します。

    • 配列の値は、フィルタリングに失敗した場合はFALSE、そもそも変数が設定されていない場合はNULLを返します。
    • なお、フラグFILTER_NULL_ON_FAILUREが指定されている場合は逆になります。(失敗時=>NULL, 未設定=>FALSE)←これは私の環境ではnullしか返りませんでした。
  • 失敗時には、FALSEを返します。

こちらは、PHPの公式ドキュメントに近い形で書きます。

ソース

<?php
/**
 * POSTリクエストで来る情報サンプル
 * $_POST = array(
 *   'product_id' => 'libgd<script>',
 *   'version'    => '2.0.33',
 *   'categories' => array('1', '2')
 * );
 */

$args = array(
  'product_id'  => FILTER_SANITIZE_ENCODED,
  'version'     => FILTER_SANITIZE_ENCODED,
  'categories'  => array(
                      'filter' => FILTER_VALIDATE_INT,
                      'flags'  => FILTER_REQUIRE_ARRAY
                    )
);

$input_data = filter_input_array(INPUT_POST, $args);
var_dump($input_data);

?>
<html>
  <head>
    <meta charaset="utf-8">
  </head>
  <body>
    <form method="post">
    <label>製品ID:<input type="text" name="product_id"></label><br>
    <label>バージョン:<input type="text" name="version"></label><br>
    カテゴリ:<label><input type="checkbox" name="categories[]" value="1">カ1</label><label><input type="checkbox" name="categories[]" value="2">カ2</label><br>
    <input type="submit" value="送信">
    </form>
  </body>
</html>

結果

array (size=3)
  'product_id' => string 'libgd%3Cscript%3E' (length=17)
  'version' => string '2.0.33' (length=6)
  'categories' =>
    array (size=2)
      0 => int 1
      1 => int 2

filter_varメソッド

mixed filter_var(mixed $valiable [, int $filter = FILTER_DEFAULT [, mixed $options]])
@param mixed $valiable フィルタリングする値
@param int   $filter   適用するフィルタ定数(またはその値)
@param mixed $options  オプションあるいはフラグの論理和の連想配列。

filter_varメソッドは、指定したフィルタでデータをフィルタリングすることが出来ます。

基本的に、filter_inputと機能は同一です。

返り値は、フィルタリングされたデータです。処理に失敗するとFALSEを返します。

例(公式と同様です)

ソース

<?php
var_dump(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL));
var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));

結果

string(15) "bob@example.com"
bool(false)

filter_var_arrayメソッド

mixed filter_var_array(array $data [, mixed $definition [, bool $add_empty = true]])
@param array $data 文字列キーの配列を指定します。(array('key' => data))
@param mixed $definition 定義した配列または、フィルタ定数を指定します。
@param bool  $add_empty 存在しないキーはNULLとして返り値に追加をします。

filter_var_arrayメソッドは複数の変数を受け取り、それらをフィルタリングすることが出来ます。

内容としては、filter_input_arrayメソッドと同一の機能を持ちます。

第2引数のdefinitionに関して(filter_input_arrayと同一です)

第2引数のdefinitionの指定の仕方は複数有ります。(公式の情報は少しわかりにくいです。)

使用できるのは

  • 引数を定義する配列

    • 配列のキーには、対象となる変数名の文字列を指定します。
    • 対応する値はフィルタの定数(または対応する値)または、配列となります。
      • 配列の形式は、(‘filter’=>フィルタの定数, ‘flags’ => フィルタを適用するフラグ, ‘options’=>フィルタに適用するオプション)となってます。
  • フィルタの定数または、それに対応する値

    • この場合、入力配列すべてに対して、フィルタ処理がされます。

戻り値に関して

戻り値は複数有ります。

  • 成功時には、要求された変数の値を含む配列を返します。

    • 配列の値は、フィルタリングに失敗した場合はFALSE、そもそも変数が設定されていない場合はNULLを返します。
    • なお、フラグFILTER_NULL_ON_FAILUREが指定されている場合はフィルタリングに失敗した場合でもNULLを返すようになります。
  • 失敗時には、FALSEを返します。

まとめと最後に

  • filterは便利。
  • 最近のフレームワークには採用されているため、覚えていて損はない
  • 多少であるが、このfilterだけでは不備な部分もあるので、少しだけ怖い

なお、こちらに記載した内容ですが、すべてを検証しているわけではなくある程度検証したものです。例に書いてある内容に関しては、
現環境または、ideoneにて確認を行ってます。

Pocket

 Posted by at 5:57 PM

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*