How to display error message when Maatwebsite Excel import fail

7.8k views Asked by At

I tried to do excel import using Maatwebsite-3.1 and Laravel-5.8:

public function import(Request $request){
    $request->validate([
        'file' => 'required|max:10000|mimes:xlsx,xls',
    ]);

    $path = $request->file('file')->getRealPath();

    try{

        Excel::import(new StudentsImport, $path);
        
    } catch (\Maatwebsite\Excel\Validators\ValidationException $e) {
        $failures = $e->failures();
        
        foreach ($failures as $failure) {
            $failure->row(); // row that went wrong
            $failure->attribute(); // either heading key (if using heading row concern) or column index
            $failure->errors(); // Actual error messages from Laravel validator
            $failure->values(); // The values of the row that has failed.
        }
    }
    
    return back()->with('status', 'Students are added successfully!');
}

class StudentsImport implements WithMultipleSheets
{
    public function sheets(): array
    {
        return [
            new FirstStudentSheetImport()
        ];
    }
}

class FirstStudentSheetImport implements OnEachRow, WithHeadingRow
{
    public function onRow(Row $row)
    {   
        $rowIndex = $row->getIndex();

        if($rowIndex >= 200)
            return; // Not more than 200 rows at a time

        $row = $row->toArray();

        $student_info = [
            'student_id'           => $tb->id,
            'birthday'             => $row['birthday']?? date('Y-m-d'),
            'religion'             => $row['religion'] ?? '',
            'first_name'          => $row['first_name'],
            'last_name'  => $row['last_name'] ?? '',
            'user_id' => auth()->user()->id,
        ];
        
        create(StudentInfo::class, $student_info);
    }
}

When the import is successful, I got success message, but when it fails, I got error-500

How do I make the application to display the error message for failure instead of the error-500?

1

There are 1 answers

0
Yassine Nat On

I was facing the same issue. On your import class you need to Implements SkipsOnError, SkipsOnFailure

your class should look like this :

class xxxImport implements ToModel,WithStartRow, WithValidation,  SkipsOnError, SkipsOnFailure 
{
     use Importable,SkipsErrors, SkipsFailures;

With this you can catch your errors from the controller Note that you can replace

Excel::import(new xxxImport,$request->file('file')); 

With

 $import =  new formationsImport;

now all failures can be found here :

$import->failures() 
<?php

namespace App\Imports;

use Throwable;
use App\xxx;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\SkipsErrors;
use Maatwebsite\Excel\Concerns\SkipsFailures;
use Maatwebsite\Excel\Concerns\SkipsOnError;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Concerns\WithValidation;

class xxxImport implements ToModel,WithStartRow, WithValidation,  SkipsOnError, SkipsOnFailure 
{
     use Importable,SkipsErrors, SkipsFailures;
    /**
    * @param array $row
    *
    * @return \Illuminate\Database\Eloquent\Model|null
    */
    public function model(array $row)
    {
        return new Formation([
            //
            'name' => $row[0],
            'description' =>$row[1],
            //etc
        ]);
    }

    /** Import startRow
     * @return int
     */
    public function startRow(): int
    {
        return 2;
    }

    public function rules():array   
    {
        # code...
        return [
            '*.0' => ['required','unique:formations,name'],
            '*.1' => ['regex:/(^[^=\-+\/\\\*%])+/','required'],
            '*.2' => ['regex:/(^[^=\-+\/\\\*%])+/','required'],
            '*.3' => ['required'],
            '*.4' => ['required'],
            '*.5' => ['required'],
            '*.6' => ['required'],
            '*.7' => ['required'],
            '*.8' => ['required'],
            '*.9' => ['required'],
            '*.10' => ['required'],
            '*.11' => ['required'],
            '*.12' => ['required'],
            '*.13' => ['required'],
            '*.14' => ['required'],
            '*.15'  => ['required','unique:formations,slug'],
        ];
    }

    public function customValidationMessages()
        {
            return [
                '0.unique' => 'Le nom de la formation existe déjà',
                '15.unique' => 'Le slug de la formation existe déjà',
            ];
    }

     public function onError(Throwable $error)
     {
        
     }

    // public function onFailure(Failure ...$failures) // 
    // {
            
    // }

your controller should look like this.

public function handleImport(Request $request)
    {
        //
            if (empty($request->file('file'))) 
            {
                return back()->with('error','custom message');
            }
            else{   
                request()->validate([
                    'file'  => 'required|mimes:xls,xlsx,csv|max:2048',
                ]);

                $pathTofile = $request->file('file')->store('xxx','public');
                
                // Excel::import(new xxxImport,$request->file('file')); 
                $import =  new xxxImport;
                $import->import($pathTofile); // we are using the trait importable in the xxxImport which allow us to handle it from the controller directly

                // dd($import->failures());
                    if($import->failures()->isNotEmpty()){
                        $failures = $import->failures();
                        
                        return view('admin.formations.failures')->with('failures', $failures);
                    }
                return back()->with('success','Formations importées avec succès');
            
            }
    }

    ```