Импорт Laravel CSV - могу ли я использовать проверку запроса? - PullRequest
0 голосов
/ 08 июня 2018

Я использую Laravel 5.6 и настроил подтверждение запроса формы для моей формы, которая отправляет одну строку, проверяет ее и затем добавляет в базу данных.Все это прекрасно работает.

Для пакетного импорта нескольких строк у меня есть импорт CSV.CSV анализируется в массив, а затем каждая строка массива содержит данные того же типа, что и в моей форме, и поэтому может использовать те же правила проверки.

Я немного растерялся, как на самом деле реализоватьэто как данные, проанализированные после CSV, находятся в массиве, а не как объект запроса, который ищет запрос проверки формы.

Есть ли у кого-нибудь какие-либо советы о том, как лучше использовать мою форму?проверка как для формы, так и для CSV без дублирования кода?

РЕДАКТИРОВАТЬ

Если кому-то интересно, мое окончательное решение состояло в том, чтобы не использовать проверку запроса формы.В моем случае было проще добавить правила проверки и сообщения в некоторые защищенные функции внутри контроллера.Это означает, что их можно повторно использовать в каждой из функций контроллера, которые в этом нуждаются (store, csvStore и т. Д.), Без дублирования кода.В этом случае я не уверен, какие преимущества дает функция проверки запроса формы.

//reformat CSV into array
$master = [];
$line_id = 1;
foreach ($data as $row) {
    //skip blank rows
    if (empty($row['sku'])) continue;
    //build master
    foreach($row as $key => $value){
        if(!empty($value)) $master[$row['sku']][$key] = $row[$key];
    }
    //add line number for debugging
    $master[$row['sku']]['line_number'] = $line_id;
    $line_id++;
}

//Validate each row of CSV individually
$error_messages = new MessageBag();
$error_count = 0;
$duplicate_count = 0;
if(empty($master)){
    //empty $master
    $error_messages->add('', 'CSV file does not contain valid data or is empty');
    flash()->message('Nothing was imported');
    return redirect()->back()->withErrors($error_messages);
} else {
    foreach($master as $row){
        $validator = Validator::make($row,$this->createValidationRules(), $this->createValidationMessages());

        //Check validation
        if ($validator->fails()){
            $master[$row['sku']]['valid'] = false;
            if(isset($validator->failed()['sku']['Unique'])){
                $duplicate_count ++;
                if(!request('ignore-duplicates') && !request('ignore-errors')) $error_messages->merge($validator->errors()->messages()); //save error messages
            } else {
                $error_count ++;
                if(!request('ignore-errors')) $error_messages->merge($validator->errors()->messages()); //save error messages
            }
        } else {
            $master[$row['sku']]['valid'] = true;
        }
    }
}

//add successful rows to DB
$success_count = 0;
foreach($master as $row){
    if($row['valid'] == true){
        $productCreate = new ProductCreate();
        $productCreate->create($row);
        $success_count++;
    }
}

Затем я использовал счетчик успехов / ошибок / дубликатов, чтобы отправить обратно подходящую сумку сообщений об ошибках и / или флэш-сообщения.

1 Ответ

0 голосов
/ 08 июня 2018

Вы можете подойти к нему, создав макрос объекта Request, чтобы превратить CSV в массив, а затем использовать промежуточное ПО для анализа входящего запроса, если это CSV-файл, и слияния его с входящим запросом.Тогда проверка вашего приложения может проверить его с помощью проверки массива.

Начните с того, что заставите поставщика услуг разместить ваш макрос запроса:

php artisan make:provider RequestMacroParseCsvProvider

Затем в поставщике услуг:

Добавьте это вверху, чтобы получить класс запросов:

use Illuminate\Http\Request;

Внутри метода регистра провайдера:

Request::macro('parseCsv', function ($fileNameKey) {
    // Note: while working inside of the request macro closure, you can access the request object by referencing $this->{key_of_request_item}

    // You will be running your parser against $fileNameKey which will be the key of the request file coming in. So you'd access it like:
    if ($this->hasFile($fileNameKey)) {
        // Your code to parse the csv would go here. Instantiate your csv parsing class or whatever...
        // $file = $this->file($fileNameKey);
        // Store the parsed csv in an array, maybe named $parsedCsv?
    }

    return empty($parsedCsv) ? [] : $parsedCsv;
});

Зарегистрируйте поставщика услуг в своем config/app.php

App\Providers\RequestMacroParseCsvProvider::class,

Создайте промежуточное ПО для проверки, содержит ли входящий запрос csv

php artisan make:middleware MergeCsvArrayIntoRequest

В методе handle:

if ($request->has('your_csv_request_key)) {
    $parsedCsv = $request->parseCsv('your_csv_request_key');

    // Then add it into the request with a key of 'parsedCsv' or whatever you want to call it
    $request->merge(['parsedCsv' => $parsedCsv]);
}

return $next($request);

Зарегистрируйте ваше промежуточное ПО в app/Http/Kernel.php:

protected $middleware = [
    ...
    \App\Http\Middleware\MergeCsvArrayIntoRequest::class,
    ...
];

Или введите его в $routeMiddleware, если вы не хотитебыть глобальным.

'parse.csv' => \App\Http\Middleware\MergeCsvArrayIntoRequest::class,

Теперь ваше промежуточное ПО перехватывает и конвертирует любые загруженные вами CSV-файлы, и вы можете проверить parsedCsv ключ запроса с помощью проверки массива Laravel .

Вы можете сделать некоторые улучшения, чтобы сделать его более гибким, если хотите.Я сделал нечто похожее, но не совсем связанное с файлами, в другом проекте, где мне нужно было изменить запрос, прежде чем он добрался до проверки моего контроллера, и он заработал.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...