Laravelの「integer」ルールのバリデーション

概要

LaravelのValidationルールで「integer」があるが、これは型までチェックしているのか?と思ったのが調べるきっかけ。

どういうことかというと、

'id' => 'required|integer',

と書いていたバリデーションルールに対して、string型での数値が通っていた。

LaravelにおけるValidationの流れ

そもそもの話

ざっくり書くとControllerでこのようにValidationを実行しているが、

use ValidatesRequests;

$this->validate($request, $this->validator->getRules(), $this->validator->getMessage(), $this->validator->getAttribute());

このときの処理の流れは、

vendor\laravel\framework\src\Illuminate\Foundation\Validation\ValidatesRequests.php: validate()

vendor\laravel\framework\src\Illuminate\Validation\Validator.php: validate()

vendor\laravel\framework\src\Illuminate\Validation\Validator.php: fails()

vendor\laravel\framework\src\Illuminate\Validation\Validator.php: passes()

vendor\laravel\framework\src\Illuminate\Validation\Validator.php: validateAttribute()

Validationの実体

validateAttributeの中身がこんな感じ

/**
 * Validate a given attribute against a rule.
 *
 * @param  string  $attribute
 * @param  string  $rule
 * @return void
 */
protected function validateAttribute($attribute, $rule)
{
    $this->currentRule = $rule;

    list($rule, $parameters) = ValidationRuleParser::parse($rule);

    if ($rule == '') {
        return;
    }

    // First we will get the correct keys for the given attribute in case the field is nested in
    // an array. Then we determine if the given rule accepts other field names as parameters.
    // If so, we will replace any asterisks found in the parameters with the correct keys.
    if (($keys = $this->getExplicitKeys($attribute)) &&
        $this->dependsOnOtherFields($rule)) {
        $parameters = $this->replaceAsterisksInParameters($parameters, $keys);
    }

    $value = $this->getValue($attribute);

    // If the attribute is a file, we will verify that the file upload was actually successful
    // and if it wasn't we will add a failure for the attribute. Files may not successfully
    // upload if they are too large based on PHP's settings so we will bail in this case.
    if ($value instanceof UploadedFile && ! $value->isValid() &&
        $this->hasRule($attribute, array_merge($this->fileRules, $this->implicitRules))
    ) {
        return $this->addFailure($attribute, 'uploaded', []);
    }

    // If we have made it this far we will make sure the attribute is validatable and if it is
    // we will call the validation method with the attribute. If a method returns false the
    // attribute is invalid and we will add a failure message for this failing attribute.
    $validatable = $this->isValidatable($rule, $attribute, $value);

    if ($rule instanceof RuleContract) {
        return $validatable
                ? $this->validateUsingCustomRule($attribute, $value, $rule)
                : null;
    }

    $method = "validate{$rule}";

    if ($validatable && ! $this->$method($attribute, $value, $parameters, $this)) {
        $this->addFailure($attribute, $rule, $parameters);
    }
}

これを見ると、integerの場合、validateInteger でvalidationが実行されそう。

なので追ってみた。

$method = "validate{$rule}";

if ($validatable && ! $this->$method($attribute, $value, $parameters, $this)) {
    $this->addFailure($attribute, $rule, $parameters);
}
/**
 * Validate that an attribute is an integer.
 *
 * @param  string  $attribute
 * @param  mixed   $value
 * @return bool
 */
public function validateInteger($attribute, $value)
{
    return filter_var($value, FILTER_VALIDATE_INT) !== false;
}

ということで、結局は filter_var($value, FILTER_VALIDATE_INT)

FILTER_VALIDATE_INTを調べた

とりあえず読んでみた

php.net

It's good to remember that using filter_var is primarily for filtering input values when doing boolean logic comparisons. Take the following:

$value = "12";
if(filter_var($value, FILTER_VALIDATE_INT))
{
    // validated as an int
}

これを読むと Stringっぽくクォートで囲った値を送っても、intとして処理が通りそう。

結論

型というより、整数形式の表現だったら、何でも通るのではないかと思った。

補足

1ヶ月くらい前に下書きで書いてて、公開するの忘れてたやつ。