tl;dr
-
filter_var('1 ', FILTER_VALIDATE_INT)
としたときの戻り値は1
- これが引き金になってLaravelのバリデーションルールに
integer
を使っても'1 '
が素通りする
はじめに
PHPの標準関数には罠があるものが数多ありますが、今回はfilter_var
関数の罠について書きます。
filter_var
関数とは
指定したフィルタでデータをフィルタリングする
とのことです。巷ではバリデーションに使われているようです。
罠
以下のコードを実行したときの戻り値はどうなるでしょうか。
filter_var('1 ', FILTER_VALIDATE_INT);
このコードによって 1
が返ってきます。いかにもPHPらしいですね。
実行結果は https://wandbox.org/permlink/m4jD8Iiktn4VaQXb でご覧になれます。
filter_var
関数の第2引数に渡しているFILTER_VALIDATE_INT
はPHP: 検証フィルタ - Manualによると以下の効果があります。
値が整数であるかどうか、オプションで指定した範囲内にあるかどうかを検証し、成功した場合は整数に変換します。
'1 '
が整数であるかどうかについて、PHP的には整数ということですね。
検証としてはどうなんだろうと思うところであります。
Laravelにおける落とし穴
Laravelのバリデーションルールとしてinteger
を使ったときに呼ばれるメソッドに利用されています。
https://github.com/laravel/framework/blob/fe1ef6570d10c955da8e90c8be429d96ad5574ee/src/Illuminate/Validation/Concerns/ValidatesAttributes.php#L813-L823
/**
* Validate that an attribute is an integer.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
protected function validateInteger($attribute, $value)
{
return filter_var($value, FILTER_VALIDATE_INT) !== false;
}
つまり、Laravelではバリデーションルールinteger
を使っても'1 '
は整数であると認識されます。そして、バリデーションを通過した値を得るにしてもfilter_var
関数を通した値が得られるわけではなく、元の入力値が得られます。
なので、たとえばCarbon
オブジェクトのyear
などに代入しようとするとErrorException (A non well formed numeric value encountered)
となります。
おわりに
いかにもPHPらしい感じです。気をつけましょう。