You are here
Home > !Laravel > バリデーション (5) 最大値と最小値

バリデーション (5) 最大値と最小値

バリデーション言語ファイルを編集するときにお気づきと思いますが、Laravel標準バリデーション MaxMin は(他に SizeBetween も)調査対象の属性の型でその挙動を変えます。

'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'),    // 開始日判定にはならない

 

日付の最大値と最小値

日付型の属性の前後関係の判定には、専用の afterbefore が用意されています。
しかも、引数の文字列は strtotime で処理されるので次のような指定が可能です。

'date_start' => 'date|after:today',    // 今日より大(明日以降)
'date_end'   => 'date|befor:+1 year',  // 1年以内

または属性名を引数に持つことができるので、期間指定のバリデーションに使うことが出来ます。

'date_end'   => 'datetime|after:date_start',

invalid_period

ただし、after, befor の比較は等号を含みませんので注意が必要です。

 

数値型のカスタムバリデーション

例えば1以上の整数(自然数)を判定するカスタムバリデーション natural_number を作成した場合、それを minmax で大小判定したときは、正しく数値として判定されるでしょうか?

結論を言えば、カスタムバリデーション natural_number は(そのままでは)、入力された値が数値であっても、文字列として判断され、文字数でカウントされてしまいます。

'quantity' => 'requied|natural_number|max:10', // 10桁( 10億)まで可

 

では、数値として認められるにはどのようにしたら良いのでしょうか。

vender の Validation.php でコードを追うと、getSize() メソッドにおいて次のように型判定されていることがわかります。

1 入力値が数値(is_numeric)でバリデーションに numericinteger があれば、その値を返す
2 入力値が配列(is_array)なら配列の個数を返す
3 入力値が File インスタンスならファイルサイズを kB で返す
4 それ以外は文字数(mb_strlen)を返す

数値として判定されるには、入力された値が数値であるかどうかだけでなく、バリデーションに numericinteger が含まれなければなりません。これでは他のどんなルールであっても数値と判定されることはないのです。

 

numericRules

この数値と判断されるためのバリデーションルールは、変数 $numericRules で定義されていました。

protected $numericRules = ['Numeric', 'Integer'];

カスタムバリデーションとして数値型のルールを自作した場合には、これにルール名を追加すればよいわけです。

変数 $numericRulesprotected で再定義して上書きするか、コンストラクタで必要分だけ追加します。……再定義する場合は NumericInteger を忘れずに。

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;
}

Leave a Reply

Top