Laravel 的验证器通过“可为空”规则传递空字符串

Posted

技术标签:

【中文标题】Laravel 的验证器通过“可为空”规则传递空字符串【英文标题】:Laravel's validator passes for empty string with 'nullable' rule 【发布时间】:2017-10-17 23:07:43 【问题描述】:

例子:

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

输出:

[]

x 为 null 或 1,2,3 等时,它工作正常。

x 是除空字符串之外的其他内容时,验证器表示错误。

数据库中的列可以是 NULL 或正整数,所以当我传递空字符串时,验证器告诉我这很好,但 mysql 会抛出异常,因为它试图将 ''(空字符串)保存在可为空的整数列中。

字段的唯一允许值是:null1,2,3,4,...,其他一切都应该失败。

如果我添加 required 规则,则验证器会因 null 值('nullable|required|integer|min:1')而失败

【问题讨论】:

规则nullable 只说,该值可以是null,但它不会将空值转换为null 本身。 该值不为空,因此nullable 在这里实际上并不有效。如果你这样做 Validator::make(['x' => ''], ['x' => 'integer|min:1'])->errors()->all(); 你仍然没有错误 【参考方案1】:

Laravel 5.4 带有一个全局中间件,默认将所有空字符串转换为 null。如果您不想这样做,请从列表中注释掉中间件。

app/Http/Kernel.php

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

【讨论】:

【参考方案2】:

通读源码有这个功能(在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);

函数presentOrRuleIsImplicit 基本上表示如果值为'',则仅在规则为“隐式”时才验证它(基本上如果需要属性)。

在这种情况下,如果它既是必需的又可为空的验证将失败,因为'' 与 null 不同。

Laravel 5.4 有一个名为 ConvertEmptyStringsToNull 的内置中间件,它通过获取所有 '' 值并将它们转换为 null 来帮助处理这种差异。

【讨论】:

以上是关于Laravel 的验证器通过“可为空”规则传递空字符串的主要内容,如果未能解决你的问题,请参考以下文章

在 Typescript 中将可为空的对象值转换为字符串

如何使用 Scala 在 DataFrame 中添加新的可为空字符串列

如何在mysql(laravel)中使varchar可为空且唯一

00008 - layui 表单验证,需要验证,但非必输

“不存在”是不是有验证规则?

WCF中可为空值类型的错误