How to display a validation message if name field is duplicate in the uploaded file?
<?php
namespace App\Imports;
use App\Models\Customer;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithValidation;
class CustomerImport implements ToCollection, WithHeadingRow, WithValidation
{
public $timestamps = false;
public function collection(Collection $rows)
{
foreach ($rows as $row) {
Customer::create([
'name' => $row['name'],
'address' => $row['address'],
]);
}
}
public function rules(): array
{
return [
'name' => [
'required',
'max:50',
'unique:customers,name',
],
'address' => [
'required',
'max:50',
'unique:customers,address',
]
];
}
}
My sample uploaded csv file is as follows: The name 'AAA' is duplicate. So I need to get validation error message displayed for duplicate entry in the file.
Name,Address
AAA,testaddress
AAA,testaddress1
BBB,address2
Right now I am getting Illuminate\Database\QueryException SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'AAA' error.
My Controller Code is as follows:
public function uploadFile(Request $request)
{
$request->validate(
['file' => ['required', 'file', 'mimes:txt,csv']],
['file.required' => 'Please upload the file']
);
try {
Excel::import(new CustomerImport(), $request->file('file'));
} catch (\Maatwebsite\Excel\Validators\ValidationException $e) {
$failures = $e->failures();
return redirect()
->route('customers.upload')
->withErrors($failures);
}
return redirect()
->route('customers.index')
->with('success', __('customers.message_uploaded'));
}
You can achieve this by creating a custom validation rule. An example implementation using Maatwebsite library can be:
app\Rules\CsvUnique.phpnamespace App\Rules;
use App\Imports\CustomerImport;
use Illuminate\Contracts\Validation\Rule;
use Maatwebsite\Excel\Facades\Excel;
class CsvUnique implements Rule
{
public function __construct($column)
{
$this->column = $column;
}
public function passes($attribute, $value)
{
$data = Excel::toArray(new CustomerImport(), $value);
$names = array_map(function($i) {
return $i[0];
}, array_slice($data[0],1));
return count($names) === count(array_unique($names));
}
public function message()
{
return 'The :attribute has already been taken.';
}
}
Then you can use it inside your validation logic like this:
$request->validate(
['file' => ['required', 'file', 'mimes:txt,csv', new CsvUnique('name')]],
['file.required' => 'Please upload the file']
);
Note that we pass the column name, in this canse name to the custom rule.