I'm trying to validate some data that comes from an excel file, my goal is:
- get excel file from user
- read data and pass through validator
- return list of errors or "successful" message
Now I've tried two ways but they aren't working like I want. The first way is using Laravel Excel validation, but this stops every time a row has something wrong making the validating super tedious as I have to keep uploading a modified file for every time it finds an error. I want a full list of errors.
try {
Excel::import(new SalePointValidate, $request->file('excel'));
return response()->json(['success' => true]);
} catch (\Maatwebsite\Excel\Validators\ValidationException $e) {
$failures = $e->failures();
$errors = [];
foreach ($failures as $failure) {
$errors[] = [
'row' => $failure->row(), // row that went wrong
'attribute' => $failure->attribute(), // either heading key (if using heading row concern) or column index
'errors' => $failure->errors(), // Actual error messages from Laravel validator
'values' => $failure->values() // The values of the row that has failed.
];
}
return response()->json(['success' => false, 'errors' => $errors], 200);
} catch (\Exception $e) {
Log::error($e);
return response()->json(['success' => false], 500);
}
Here is the import file
class SalePointValidate implements ToModel, WithValidation, WithHeadingRow, WithChunkReading
{
private $errors = [];
public function model(array $row)
{
return null;
}
public function chunkSize(): int
{
return 100;
}
public function rules(): array
{
return [
'*.nombre' => ['required', Rule::unique(SalePoint::class, 'name')],
'*.nombre_comercial' => ['required', Rule::unique(SalePoint::class, 'business_name')],
'*.latitud' => ['required', 'numeric'],
'*.longitud' => ['required', 'numeric'],
'*.canal' => ['required', Rule::exists(Channel::class, 'name')],
'*.cadena' => ['required', Rule::exists(Chain::class, 'name')],
'*.formato' => ['required', Rule::exists(Format::class, 'name')],
'*.pais' => ['required', Rule::exists(Country::class, 'name')],
'*.provincia' => ['required', Rule::exists(Province::class, 'name')],
'*.canton' => ['required', Rule::exists(Canton::class, 'name')],
'*.distrito' => ['required', Rule::exists(District::class, 'name')],
];
}
public function onFailure(Failure ...$failures)
{
foreach ($failures as $failure) {
$this->errors[] = $failure;
}
}
public function getErrors()
{
return $this->errors;
}
}
I also tried this but this I'm not sure what's up
$excel = Excel::toArray(new SalePointValidate, $request->file('excel'));
Validator::make($excel, [
'*.nombre' => ['required', Rule::unique(SalePoint::class, 'name')],
'*.nombre_comercial' => ['required', Rule::unique(SalePoint::class, 'business_name')],
'*.latitud' => ['required', 'numeric'],
'*.longitud' => ['required', 'numeric'],
'*.canal' => ['required', Rule::exists(Channel::class, 'name')],
'*.cadena' => ['required', Rule::exists(Chain::class, 'name')],
'*.formato' => ['required', Rule::exists(GpsFormat::class, 'name')],
'*.pais' => ['required', Rule::exists(Country::class, 'name')],
'*.provincia' => ['required', Rule::exists(Province::class, 'name')],
'*.canton' => ['required', Rule::exists(Canton::class, 'name')],
'*.distrito' => ['required', Rule::exists(District::class, 'name')],
])->validateWithBag('test');
This returns this which is incorrect cause the file does have stuff in it, the same file fails with the first method but for the actual validation errors, this just says it's required when it is there.
["El campo "0.cadena" es obligatorio."]
["El campo "0.canal" es obligatorio."]
["El campo "0.canton" es obligatorio."]
["El campo "0.distrito" es obligatorio."]
["El campo "0.formato" es obligatorio."]
["El campo "0.latitud" es obligatorio."]
["El campo "0.longitud" es obligatorio."]
["El campo "0.nombre" es obligatorio."]
["El campo "0.nombre_comercial" es obligatorio."]
["El campo "0.pais" es obligatorio."]
["El campo "0.provincia" es obligatorio."]
"El campo \"0.nombre\" es obligatorio. (and 10 more errors)"
How can I get that full list of errors using either method ?