Search code examples
phplaravellaravel-5.6dingo-api

Empty string validates for not required integer


I have to validate an input field of my API where the value has to be an integer between 1 and 100 or null or it is not even set (not required).

Thereby, my validation rule is: 'privacy_status' => "nullable|integer|min:1|max:100",

This works fine until I get an empty string as value. Since Laravel validation on a empty string validates only if field is implicit, all my other rules integer, nullable or min, max are ignored.

protected function isValidatable($rule, $attribute, $value)
{
    return $this->presentOrRuleIsImplicit($rule, $attribute, $value) &&
       $this->passesOptionalCheck($attribute) &&
       $this->isNotNullIfMarkedAsNullable($attribute, $value) &&
       $this->hasNotFailedPreviousRuleIfPresenceRule($rule, $attribute);
}

protected function presentOrRuleIsImplicit($rule, $attribute, $value)
{
    if (is_string($value) && trim($value) === '') {
        return $this->isImplicit($rule);
    }

    return $this->validatePresent($attribute, $value) || $this->isImplicit($rule);
}

Is there a way to validate this properly?


Solution

  • EDIT

    You can always create a custom validation rule.

    Validator::extendImplicit('fail_on_empty_string', function($attribute, $value, $parameters)
    {
        return $value === "" ? false : $value;
    });
    

    You can use the new rule like this:

    'privacy_status' => "fail_on_empty_string|nullable|integer|min:1|max:100",
    

    Old answer

    This is described in the Laravel documentation and is a bug you introduced yourself (though probably unconsciously): https://laravel.com/docs/5.6/validation#a-note-on-optional-fields:

    By default, Laravel includes the TrimStrings and ConvertEmptyStringsToNull middleware in your application's global middleware stack. These middleware are listed in the stack by the App\Http\Kernel class. Because of this, you will often need to mark your "optional" request fields as nullable if you do not want the validator to consider null values as invalid.

    Empty string are automatically cast to null, which by your validation is perfectly fine. Either disable the middleware, change it or alter your validation rules.