如果规则失败,Laravel $validator->validated()方法应该抛出一个异常,但是当我使用一个正在进行验证的值数组并结合了一个定制的验证规则时,没有抛出异常.

因此,我在routes/api.php文件中有以下示例:

<?php

use App\Rules\Uppercase;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;

Route::get('/validation', function () {
    $data = [
        'name' => 'testname',
        'environments' => [
            'testenv1',
            'testenv2',
        ]
    ];
    $validator = Validator::make($data, [
        'name' => ['required', 'string', 'min:5', 'max:255'],
        'environments' => [
            'required',
            'nullable',
            'array',
            new Uppercase
        ]
    ]);
    try {
        $validator->validated();
    } catch (Exception $e) {
        dd('caught by the exception thrown', $e->validator->failed());
    }

    dd('nothing happened');
})->name('validation');

现在,当我运行上面的用例,而不是像我预期的那样接收到ValidationException异常时,因为我提供的环境数据都是小写的,所以会显示"Nothing Happen"字符串.

我使用的自定义验证规则是Laravel文档大写规则的修改版本,以支持一组值,而不仅仅是一个字符串-&gt;https://laravel.com/docs/10.x/validation#custom-validation-rules 实际的大写自定义验证规则如下所示:

<?php

namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Translation\PotentiallyTranslatedString;

class Uppercase implements ValidationRule
{
    /**
     * Run the validation rule.
     *
     * @param Closure(string): PotentiallyTranslatedString $fail
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        foreach ($value as $index => $item) {
            if (strtoupper($item) !== $item) {
                $fail('The :attribute must be uppercase.');
            }
        }
    }
}

更深入地研究,我发现$validator->validated()方法判断以决定是否抛出异常的第一件事是$validator->invalid()方法,而该方法又包含以下行: $failed = Arr::only(Arr::dot($invalid), array_keys($this->failed()));,并且通过使用Arr::dot($invalid)而不是普通的$invalid数组,它会错过环境大写验证错误.

在我看来,这是一种错误的行为.

如果我遗漏了什么,请告诉我好吗?

推荐答案

你确实错过了一些东西,但这不是微不足道的.validatedphpdo说它可以抛出ValidationException,但首先要考虑一些条件.

如果您向下查看实现,您可以看到以下内容:

public function validated()
{
    throw_if($this->invalid(), $this->exception, $this);
    /* rest of the implementation */
}

我会让您更深入地挖掘,但重点是,验证器状态在您调用$validator->validated()的时刻不是无效的,因为它还没有被验证.判断它的一种方法是编写以下简单的有害程序测试:

test('uppercase validation rule when validating the validator', function () {
    $data = [
        'name' => 'testname',
        'environments' => [
            'testenv1',
            'testenv2',
        ],
    ];

    $validator = Validator::make($data, [
        'name' => ['required', 'string', 'min:5', 'max:255'],
        'environments' => [
            'required',
            'nullable',
            'array',
            new Uppercase,
        ],
    ]);

    $validator->validate();
    $validator->validated();

    $this->fail('should have thrown an exception');
})->throws(ValidationException::class);

test('uppercase validation rule when not validating the validator', function () {
    $data = [
        'name' => 'testname',
        'environments' => [
            'testenv1',
            'testenv2',
        ],
    ];

    $validator = Validator::make($data, [
        'name' => ['required', 'string', 'min:5', 'max:255'],
        'environments' => [
            'required',
            'nullable',
            'array',
            new Uppercase,
        ],
    ]);

    $validator->validated();
})->throwsNoExceptions();

因此,您只需记住首先调用$validator->validate()方法

Laravel相关问答推荐

当使用Craftable PRO时,Wysiwig是什么时候生成的?

vagrant会损坏你的电脑. | macOS v12(蒙特雷)#13132

Ziggy 路由默认为查询字符串

如何在 laravel livewire 中按 bool 值排序数组

使用 Laravel 计算页面浏览量

如何判断用户Electron邮件是否已存在

如何在 Laravel 中显示渲染时间/页面加载时间?

Laravel - 排序的集合输出不是数组

Laravel 扩展验证自定义消息

laravel 5 - assets资源 list 中未定义 css 文件?

在 php Laravel 5 中创建自定义帮助函数的最佳实践是什么?

验证匹配字符串

脚本 php artisan clear-compiled 处理 pre-update-cmd 事件返回错误(Laravel 4.1 升级)

Laravel Passport 通过访问令牌获取客户端 ID

反向代理后面的 Laravel 路由

Laravel 字符串验证以允许空字符串

Laravel 4 验证唯一(数据库)忽略当前

Laravel 5 - 判断日期是否是今天

Laravel 单元测试依赖注入

在 Laravel 中判断会话超时