You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中StudentSchedule Observer的updated事件未触发问题

Laravel Observer updated事件不触发问题

问题概述

StudentSchedule模型的Observer中,created事件可正常触发并记录日志,但updated事件完全不执行,已确认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');
    // 注释的业务逻辑代码
}

控制器更新代码

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

Observer注册代码(ObserverProvider)

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

问题原因

你使用的是查询构造器的批量更新方法:StudentSchedule::whereIn()->update(),这种方式直接生成SQL语句操作数据库,不会加载任何Eloquent模型实例,因此不会触发模型的updated事件,自然也不会执行Observer中的updated方法。

而created事件正常工作,是因为创建模型时依赖Eloquent的create()/模型实例save()方法,会完整触发模型生命周期事件。

解决方案

要触发Observer的updated事件,必须通过Eloquent模型实例执行更新操作,以下是两种可行方式:

方式1:查询模型实例后逐个更新(适合数据量不大的场景)

修改控制器代码,先通过get()获取模型集合,再遍历调用update():

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

方式2:手动触发事件(适合大数据量场景,避免内存占用过高)

如果数据量较大,逐个加载模型会占用过多内存,可以在批量更新后手动触发事件:

public function dropSchedules(Request $request)
{
    $ids = $request->student_schedules;
    // 批量更新数据库
    StudentSchedule::whereIn('id', $ids)->update(['final_grade' => 'DRP']);
    
    // 手动触发updated事件
    foreach ($ids as $id) {
        $schedule = StudentSchedule::find($id);
        if ($schedule) {
            event(new \Illuminate\Database\Events\Updated($schedule));
            // 或者直接调用Observer的方法
            // app(StudentScheduleObserver::class)->updated($schedule);
        }
    }
    
    return response()->json([
        'message' => 'Student schedules successfully dropped.'
    ], 200);
}

验证结果

修改后,Observer中的updated方法会被触发,Log::info('updated log')会正常输出日志,后续业务逻辑也能正常执行。

内容的提问来源于stack exchange,提问作者Kael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 06:06:17