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らしい感じです。気をつけましょう。