Laravel 验证海量数据超时

问题描述 投票:0回答:2

我有 laravel FormRequest,它准备验证规则。我在最后转储了prepareForValidation 函数,它立即显示转储。但是当我尝试在控制器中调用

$request->validation()
函数时,需要很长时间。我有类似
required|numeric|max:999999.99|min:0|email
的验证。当我发送 1000 个项目时,每个项目几乎包含 45 个字段。

在我的代码端进行此验证之前没有任何操作。有什么解决办法来处理此类事情吗?请求通过 api 发送。

laravel api validation request
2个回答
1
投票

Laravel 验证对于大型数组来说很慢。我已向 Laravel 发送了 issuePR 来修复它。我的 PR 没有被接受。 在修复 Laravel 之前你现在可以做什么:

  1. 对于数组验证,将验证数组大小与验证项分开。这可以确保当用户向您发送大型数组时,您的服务器 CPU 不会被浪费:
$request->validate(['array' => 'required|array|max:100']);
$request->validate(['array.*' => 'required|numeric|max:1000']);
  1. 如果可能,请将 API 设计为不采用大型数组。不管验证速度如何,接受大型数组毕竟不是最佳实践。不接受大小为 10,000 的数组。如果用户需要向您的服务器发送 10,000 条记录,也许他们应该通过 100 个请求发送它们,每个请求包含 100 条记录。
  2. 您还可以以较小的数据块验证数据以提高性能。
collect($request['array'])->chunk(100)->each(function (array $chunk) {
    Validator::validate(
        ['array' => $chunk],
        ['array.*' => 'required|numeric|max:1000']); 
});
  1. 您始终可以选择通过 Laravel 验证以外的方式来验证输入。它可能比你想象的要简单。

0
投票

Laravel 验证非常慢,维护者的官方立场是您应该做一些与验证大负载不同的事情。我认为事实更加微妙,有时对大型 HTTP 有效负载进行验证就很好。

我没有使用内置的 Laravel 验证,而是新建了 PHP 类,速度超级快。

这是一个帮助您入门的概念。差异是显着的。

<?php

declare(strict_types=1);

readonly class SpeedTest {
    public function __construct(public int $room_id, public string $external_id)
    {
        throw_if($this->room_id < 0, new \DomainException("Example of a validation rule"));
    }
}

$payload = array_map(fn($i) => ['room_id' => $i, 'external_id' => "string_{$i}"], range(1, 5000));

\Illuminate\Support\Benchmark::dd([
    'validation' => fn() => \Illuminate\Support\Facades\Validator::validate([
        'array' => $payload,
    ], [
        'array.*.room_id' => 'required|integer',
        'array.*.external_id' => 'required|string',
    ]),
    'newing_up' => fn() => array_map(fn($i) => new SpeedTest(...$i), $payload)
], 1);

结果:

"validation" => "636.862ms"
"newing_up" => "15.103ms"

如果您想要 422 而不是 500,您可以捕获此代码中引发的异常并返回 422。根据您的用例,您可以省略或确保包含

declare(strict_types=1);

© www.soinside.com 2019 - 2024. All rights reserved.