拉拉维尔 |大量数据的特殊验证

Posted

技术标签:

【中文标题】拉拉维尔 |大量数据的特殊验证【英文标题】:Laravel | Special validation of a lot of data 【发布时间】:2020-01-20 16:44:19 【问题描述】:

数据验证(1 - 10000 行可能)

因此,为了提供一些上下文,我正在创建一个基于 Web 的映射界面,以将其他数据格式映射到我们的格式。

问题

获取数据数组和格式数组,如下所示:

$vehicle = [
    'cost' => '$159',
    'reconditioning' => '$140'
];

$formats = [
    'cost' => 'integer',
    'reconditioning' => 'integer'
];

检查所有字段是否与我们的数据结构不一致,例如“total_cost”将是数据中的错误,因为其中包含非数字字符。验证的输出必须为每个单独的字段显示一个错误,如下所示(真正的意思是该字段有错误):

$vehicle_errors = [
    'total_cost' => true, 
    're_condition' => true
];

验证后,我将显示有错误的字段供用户更正。

我已经成功完成了所有这些工作,但是我使用 for 循环和 switch case 来验证每个单独的字段,当我们拥有超过几千辆汽车时,这会成为一个问题。

我的尝试

我曾尝试使用 for 循环成功地完成此操作,但 php 要求我将“max_input_vars”增加到我想尽量避免的很多,因为此操作对我的服务器造成了沉重的负担。 我也尝试过 Laravel 验证,它没有给我想要的输出,并且也遇到了与使用 for-loops 相同的问题,出现 php 错误。

可能的解决方案

我知道有一种方法可以验证 mysql 表中的数据并获得类似于我需要的输出,这将解决我的问题,因为它使用 mysql 服务器资源,但我不知道如何完成此操作,但在网上找不到有关此主题的任何内容。

【问题讨论】:

将数组分成块。 无论解决方案如何,都将您的请求分解为多个。为每 100 个条目(例如)制作一个带有 ajax 调用的前端进度条,并在最后显示结果(100%) 感谢您的建议,我将尝试按照@MatthewDaly 的建议使用生成器,我会用我的结果更新这篇文章。 @MatthewDaly 你能否提供一些示例代码来展示我如何使用它来解决我的数据验证问题?我一直在环顾四周并尝试不同的方法,但我不完全理解这将如何提供一种在执行验证逻辑时对车辆进行分类的方法。我阅读了您从 php 网站链接的文档,但我不完全了解如何将他们提供的示例应用于此问题。 【参考方案1】:

我想你想使用块。

DB::table('formats')->chunk(100, function($formats)

    foreach ($formats as $format)
    
        //perform validation
    
);

您可能还希望在命令中执行此操作,而不是在请求中执行此操作,以避免超时等问题。根据您的设置,您还可以在队列中为每个项目创建作业,或者如果修复密集,则只为验证失败的项目创建作业

【讨论】:

感谢您的建议,但是我没有通过数据库查询提取数据,这是我可以使用块的地方。此外,我还需要在同一页面上显示错误,所以我无法使用命令。 啊,我明白了。那么,用户正在发出请求,然后您的应用程序从外部服务获取这些数据或从某个地方抓取它? 是的,对不起,我忘了解释那部分,用户正在上传一个 CSV 文件,它被解析成一个车辆数组。 在那种情况下,我可能仍然不会在一个请求中处理这一切。我会将其卸载到队列中并与工作人员一起处理。我可能会存储 .csv 有一个代表导入作业的行表,其中有一列用于总行数、已处理的行数、csv 的路径、一个包含需要呈现给的错误/消息的 json 对象用户和状态枚举,然后创建一个作业来处理导入。然后,根据流量、工作数量等,将用户发送到包含他们工作的页面,或者只是抛出一个进度条 如何在 for 循环中验证? ://【参考方案2】:

听起来您在这种情况下的根本问题是数据数组太大而无法一次性加载到内存中,因此一旦数组变得太大,您的应用程序就会崩溃。

Generators 已添加到 PHP 以解决此问题。它们允许您迭代一组数据,而无需将整个数据保存在内存中,这使得处理非常大的数据集更加实用。但是,语法可能有点麻烦。

碰巧的是,新发布的 Laravel 6 以lazy collections 的形式为这个问题提供了解决方案。这些使用生成器,但提供了更友好的界面,以便您可以轻松地遍历非常大的数据集,而无需使用太多内存。这是一个使用中的例子,取自https://www.magutti.com/blog/laravel-lazy-collections:

use App\Project;
use Illuminate\Support\LazyCollection;


Route::get('/', function () 

    LazyCollection::make(function () 
        // project.csv  with 300.000 rows
        $filePath = storage_path('app/public/project.csv');
        $handle = fopen($filePath, 'r');
        while ($line = fgetcsv($handle)) 
            yield $line;
        
    )
        ->chunk(10000) //split in chunk to reduce the number of queries
        ->each(function ($lines) 

            $list = [];
            foreach ($lines as $line) 
                if (isset($line[1])) 
                    $list[] = [
                        'name' => $line[1],
                        'email' => $line[2],
                        'status_id' => $line[3]
                    ];
                
            
            // insert 10000 rows in one shot
            Project::insert($list);

        );
    /* display memory usage */
    echo number_format(memory_get_peak_usage() / 1048576, 2) . ' MB';
);

现在,当您调用 cursor() 方法时,Eloquent ORM 还会返回一个惰性集合,因此您也可以使用它来处理从数据库返回的非常大的数据集。所有这些都可以单独使用生成器来实现,但是惰性集合提供了一种更简单、更易读的方法。

【讨论】:

以上是关于拉拉维尔 |大量数据的特殊验证的主要内容,如果未能解决你的问题,请参考以下文章

错误:“未经身份验证。”拉拉维尔

拉拉维尔 |唯一验证 where 子句

required_if 带有数组验证规则的验证规则不起作用 |拉拉维尔 |验证

Laravel 图像规则验证不适用于 Laravel 8,但适用于 Laravel 7 |拉拉维尔 |图片 |验证

数据库中存在名称?拉拉维尔

拉拉维尔。测试清除活动数据库