Search code examples
laraveleloquentlaravel-8laravel-api

Model observer is not triggering while updating


I have an issue while trying to use an observer that it doesn't fire the observer only in the updated case. it works fine in other cases.

I had some research about it and I found some solutions, but unfortunately, it didn't work for me. Because it's not reaching the updated in my observer.

ScheduleObserver.

public function created(StudentSchedule $student_schedule)
    {
        Log::info('created log');
        $student = $student_schedule->student()->get()->first();
        $schedule = $student_schedule->schedule()->get()->first()->subject->subject;
        Logger::createLog("Student Schedule Added for " . $student->first_name . " " . $student->last_name . " '" . $schedule->name . "'");
    }

    /**
     * Handle the student schedule "updated" event.
     *
     * @param  \App\Models\Student\Schedule  $student_schedule
     * @return void
     */
    public function updated(StudentSchedule $student_schedule)
    {
        Log::info('updated log');
        // $student = $student_schedule->student()->get()->first();
        // $schedule = $student_schedule->schedule()->get()->first()->subject->subject;
        // $drop_students = $student_schedule->schedule()->where('id')->get();

        // foreach ($drop_students as $drop_student) {
        //     $drop_student = $student_schedule->schedule();
        // }
        // $drop_student->save(['final_grade' => 'DRP']);
        
        // if ($drop_student) {
        //     Logger::createLog("Student Schedule Removed for " . $student->first_name . " " . $student->last_name . " '" . $schedule->name . "'");
        // } else {
        //     Logger::createLog("Student Schedule Updated for " . $student->first_name . " " . $student->last_name . " '" . $schedule->name . "'");
        // }
    }

I called the update method in my controller like this:

public function dropSchedules(Request $request)
    {
        StudentSchedule::whereIn('id', $request->student_schedules)->update(['final_grade' => 'DRP']);
        return response()->json([
            'message' => 'Student schedules successfully dropped.'
        ], 200);
    }

ObserverProvider

class ObserverProvider extends ServiceProvider
{
    public function boot()
    {
        StudentSchedule::observe(StudentScheduleObserver::class);
    }
}

But only the created method gets fired

Student Schedule Added for test student 'english'

Solution

  • Observers only trigger for updates of single models. What you are doing is a mass update. There is a warning about this in the documentation

    When issuing a mass update or delete query via Eloquent, the saved, updated, deleting, and deleted model events will not be dispatched for the affected models. This is because the models are never actually retrieved when performing mass updates or deletes.

    To get the observers to work you need to change your updates to single model updates:

    public function dropSchedules(Request $request) {
            $schedulesToUpdate = StudentSchedule::whereIn('id', $request->student_schedules)->get();
            foreach ($schedulesToUpdate as $scheduleToUpdate) {
                $scheduleToUpdate->final_grade = 'DRP';
                $scheduleToUpdate->save();
            }
            return response()->json([
                'message' => 'Student schedules successfully dropped.'
            ], 200);
        }
    

    This will be slower than a mass update but it's the tradeoff to get the observers to run.