バリデーション言語ファイルを編集するときにお気づきと思いますが、Laravel標準バリデーション Max
と Min
は(他に Size
、Between
も)調査対象の属性の型でその挙動を変えます。
'max' => [ 'numeric' => ':attributeの値が:maxを超えています', 'file' => ':attributeのサイズが:max kBを超えています', 'string' => ':attributeの文字数が:maxを超えています', 'array' => ':attributeの個数が:maxを超えています', ], 'min' => [ 'numeric' => ':attributeの値が:minに足りません', 'file' => ':attributeのサイズが:min kBに足りません', 'string' => ':attributeの文字数が:minに足りません', 'array' => ':attributeの個数が:minに足りません', ],
ここで問題となるのは、文字列型が入力した文字数カウントとの比較になることです。文字列比較の大小によるバリデーションは存在してません。
例えば日付型の属性に対する開始日のつもりで Min
を指定しても、文字数判定となり、期待したバリデーションにはなりません。
'date_start' => 'date|min:'.date('Y-m-d'), // 開始日判定にはならない
日付の最大値と最小値
日付型の属性の前後関係の判定には、専用の after
と before
が用意されています。
しかも、引数の文字列は strtotime
で処理されるので次のような指定が可能です。
'date_start' => 'date|after:today', // 今日より大(明日以降) 'date_end' => 'date|befor:+1 year', // 1年以内
または属性名を引数に持つことができるので、期間指定のバリデーションに使うことが出来ます。
'date_end' => 'datetime|after:date_start',
ただし、after
, befor
の比較は等号を含みませんので注意が必要です。
数値型のカスタムバリデーション
例えば1以上の整数(自然数)を判定するカスタムバリデーション natural_number
を作成した場合、それを min
や max
で大小判定したときは、正しく数値として判定されるでしょうか?
結論を言えば、カスタムバリデーション natural_number
は(そのままでは)、入力された値が数値であっても、文字列として判断され、文字数でカウントされてしまいます。
'quantity' => 'requied|natural_number|max:10', // 10桁( 10億)まで可
では、数値として認められるにはどのようにしたら良いのでしょうか。
vender の Validation.php でコードを追うと、getSize()
メソッドにおいて次のように型判定されていることがわかります。
1 | 入力値が数値(is_numeric )でバリデーションに numeric か integer があれば、その値を返す |
---|---|
2 | 入力値が配列(is_array )なら配列の個数を返す |
3 | 入力値が File インスタンスならファイルサイズを kB で返す |
4 | それ以外は文字数(mb_strlen )を返す |
数値として判定されるには、入力された値が数値であるかどうかだけでなく、バリデーションに numeric
か integer
が含まれなければなりません。これでは他のどんなルールであっても数値と判定されることはないのです。
numericRules
この数値と判断されるためのバリデーションルールは、変数 $numericRules
で定義されていました。
protected $numericRules = ['Numeric', 'Integer'];
カスタムバリデーションとして数値型のルールを自作した場合には、これにルール名を追加すればよいわけです。
変数 $numericRules
を protected
で再定義して上書きするか、コンストラクタで必要分だけ追加します。……再定義する場合は Numeric
と Integer
を忘れずに。
public function __construct($translator, $data, $rules, $messages = []) { parent::__construct($translator, $data, $rules, $messages); $this->numericRules[] = 'NatrualNumber'; } /** * 自然数 natural_number * * @param string $attribute 検査する属性名 * @param string $value 検査する値 * @return bool */ public function validateNaturalNumber($attribute, $value) { if ($this->validateInteger($attribute, $value)) { return ($value > 0); } return false; }メルマガ購読の申し込みはこちらから。