Jackson J
Jackson J

Reputation: 1523

Laravel's validator passes for empty string with 'nullable' rule

Example:

Validator::make(['x' => ''], ['x' => 'nullable|integer|min:1'])->errors()->all();

Output:

[]

When x is null or 1,2,3, etc. it works fine.

When x is something else except empty string validator says about errors.

Column in database can be NULL or positive integer so when I pass empty string, validator tells me that it's fine, but mysql throws exception because it tries to save '' (empty string) in nullable integer column.

Only allowed values for field are: null, 1,2,3,4,..., everything else should fail.

If I add required rule then validator fails for null value ('nullable|required|integer|min:1')

Upvotes: 0

Views: 6244

Answers (2)

Sandeesh
Sandeesh

Reputation: 11906

Laravel 5.4 comes with a global middleware to convert all empty strings to null by default. If you don't want this then comment out the middleware from the list.

app/Http/Kernel.php

\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,

Upvotes: 1

apokryfos
apokryfos

Reputation: 40653

Reading through the source code there's this function (in Validator.php)

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

The function presentOrRuleIsImplicit basically says that if the value is '' then only validate it if the rule is "implicit" (basically if the attribute is required).

In that case if it is both required and nullable validation would fail because '' is not the same as null.

Laravel 5.4 has a built-in middleware called ConvertEmptyStringsToNull which basically helps deal with this discrepancy by taking all '' values and converting them to null.

Upvotes: 0

Related Questions