Search code examples
phpmysqllaravellaravel-9laravel-excel

How to perform custom tasks or fire an event while importing xlsx file via laravel excel


I'm new to laravel, I wanted to insert student details in mysql database from xlsx file. I used Laravel excel v3 to import excel file. It is working good. But along with inserting student details in 1 table, The same student id record should be made in all associative tables.

example --> if 1 student inserted in table 'student_details', then 1 record must be made in tables 'oral' and 'endsem' having foreign key as 'student_id'.

I have made event to make this records in oral and endsem tables. Now problem is how to apply that event and how to get that student_id after student is created to fire event. (Student Id will is auto_increment value)

StudentImport -->

    <?php
namespace App\Imports;

use App\Events\StudentCreated;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Validators\Failure;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\SkipsFailures;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use App\Models\StudentDetails;

class StudentsImport implements ToModel, SkipsOnFailure, WithValidation, WithHeadingRow
{
    use Importable, SkipsFailures;

    /**
    * @param Collection $collection
    */
    public function model(array $row)
   {     
        return new StudentDetails([
            'roll_no' => $row['roll_no'],
            'student_id' => $row['student_id'],
            'div' => $row['div'],
            'name' => $row['name'],
            'gender' => $row['gender'],
            'user_key' => session()->get('user_id'),
            'group_key' => $group_key
        ]);
    }

    public function onFailure(Failure ...$failures)
    {
        // Handle the failures how you'd like.
    }

    public function rules(): array
    {

        return [
            'student_id'  =>[
                'required',
                'string',
                'unique:student_details'
            ],
            'roll_no' =>[
                'required',
                'integer'
            ],
            'name' => [
                'required',
                'string',
            ]

        ];
    }

}

My main goal is to insert student record in all associative tables having foreign key 'student_id' when student is inserted in 'student_details' table. If there is any other way, please help.


Solution

  • Instead of using Maatwebsite\Excel\Concerns\ToModel you could use Maatwebsite\Excel\Concerns\OnEachRow. You'd get more control over what happens on every row.

    use App\StudentDetails;
    use Maatwebsite\Excel\Row;
    use Maatwebsite\Excel\Concerns\OnEachRow;
    
    class StudentsImport implements OnEachRow, ...
    {
        public function onRow(Row $row)
        {
            $rowIndex = $row->getIndex(); 
            $row = $row->toArray();
            // create model
            $studentDetails = StudentDetails::create([
                'roll_no' => $row['roll_no'],
                'student_id' => $row['student_id'],
                'div' => $row['div'],
                'name' => $row['name'],
                'gender' => $row['gender'],
                'user_key' => session()->get('user_id'),
                'group_key' => $group_key /* this variable doesn't seem to be defined anywhere */
            ]);
            // create related models
            $studentDetails->oral()->create([...]);
            $studentDetails->endsem()->create([...]);
        }
    }
    

    As for making this all happen within a transaction:

    DB::transaction(fn () => (new StudentsImport)->import(...));