I am using Laravel 5.6 and have setup a form request validation for my form which submits a single row, validates it and then adds to the database. This all works fine.
For batch import of multiple rows I have a CSV import. The CSV is parsed into an array, and each line of the array contains exactly the same type of data as provided in my form. Therefore it can use the same validation rules.
I am a little lost how to actually implement this; the data parsed from the CSV is in an array, and not the request object that the form validation request is looking for.
Does anyone have any tips on the best way to be able to use my form validation for both the form and CSV without duplicating code?
EDIT
If anyone is interested, my final solution was to not use the form request validation. In my case, it was easier to add the validation rules and messages to some protected functions inside the controller. This means that they can be re-used across each of the controller functions that need it (store, csvStore etc.) without duplicate code. In this case, I am not sure what advantages the form request validation feature gives.
//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++;
}
}
I then used the success/error/duplicate counts to send back a suitable error message bag and/or flash messages.