I am using Laravel-8 and Maatwebsite-3.1 package to import Excel into the DB using Laravel API as the endpoint.
Trait:
trait ApiResponse {
public
function coreResponse($message, $data = null, $statusCode, $isSuccess = true) {
if (!$message) return response() - > json(['message' => 'Message is required'], 500);
// Send the response
if ($isSuccess) {
return response() - > json([
'message' => $message,
'error' => false,
'code' => $statusCode,
'results' => $data
], $statusCode);
} else {
return response() - > json([
'message' => $message,
'error' => true,
'code' => $statusCode,
], $statusCode);
}
}
public
function success($message, $data, $statusCode = 200) {
return $this - > coreResponse($message, $data, $statusCode);
}
public
function error($message, $statusCode = 500) {
return $this - > coreResponse($message, null, $statusCode, false);
}
}
Import:
class EmployeeImport extends DefaultValueBinder implements OnEachRow, WithStartRow, SkipsOnError, WithValidation, SkipsOnFailure
{
use Importable, SkipsErrors, SkipsFailures;
public function onRow(Row $row)
{
$rowIndex = $row->getIndex();
if($rowIndex >= 1000)
return; // Not more than 1000 rows at a time
$row = $row->toArray();
$employee = Employee::create([
'first_name' => $row[0],
'other_name' => $row[1] ?? '',
'last_name' => $row[2],
'email' => preg_replace('/\s+/', '', strtolower($row[3])),
'created_at' => date("Y-m-d H:i:s"),
'created_by' => Auth::user()->id,
]);
public function startRow(): int
{
return 2;
}
}
Controller:
public function importEmployee(Request $request)
{
try {
$validator = Validator::make($request->all(), [
'document' => 'file|mimes:xls,xlsx|max:5000',
]);
if ($request->hasFile('document'))
{
if($validator->passes()) {
$import = new EmployeeImport;
$file = $request->file('document');
$file->move(public_path('storage/file_imports/employee_imports'), $file->getClientOriginalName());
Excel::import($import, public_path('storage/file_imports/employee_imports/' . $file->getClientOriginalName() ));
foreach ($import->failures() as $failure) {
$importerror = new ImportError();
$importerror->data_row = $failure->row(); // row that went wrong
$importerror->data_attribute = $failure->attribute(); // either heading key (if using heading row concern) or column index
$importerror->data_errors = $failure->errors()[0]; // Actual error messages from Laravel validator
$importerror->data_values = json_encode($failure->values());
$importerror->created_by = Auth::user()->id;
$importerror->created_at = date("Y-m-d H:i:s");
$importerror->save();
}
return $this->success('Employees Successfully Imported.', [
'file' => $file
]);
}else{
return $this->error($validator->errors(), 422);
}
}
} catch(\Throwable $e) {
Log::error($e);
return $this->error($e->getMessage(), $e->getCode());
}
}
I made it to SkipOnError and SkipOnFailure.
If there's error, it saves the error into the DB. This is working.
However, there is issue, if some rows fail it still display success (Employees Successfully Imported) based on this:
return $this->success('Employees Successfully Imported.
When there is partial upload, or all the rows or some of the rows have issues, I want to display this to the user. So that it will be interactive.
How do I achieve this?
Thanks