跳转到主内容
极星编程网:以代码为星,赴技术山海!

Laravel怎么使用观察者_Laravel怎么监听模型事件【解析】

必须手动注册模型观察者才能生效,Laravel 不自动加载;creating 在入库前触发(id 为 null),created 在插入后、事务提交前触发(id 可用);updating 仅对模型实例 save/update 有效,不响应批量更新;观察者中禁用 HTTP 请求、嵌套事务及 forceDelete。 怎么注册模型观察者(
Observer
) 观察者必须先注册才能生效,不注册等于没写。Laravel 不会自动扫描或加载
Observer
类,得手动告诉它“这个类要监听哪个模型”。 常见错误:把
UserObserver
放在
app/Observers/
下就以为完事了,结果
created
、
updated
一个都不触发。 用
boot
方法在
AppServiceProvider
里注册:
use App\Models\User; use App\Observers\UserObserver; public function boot() { User::observe(UserObserver::class); }
也可以在模型自己的
boot
方法里注册(适合单模型强耦合场景):
protected static function boot() { parent::boot(); static::observe(UserObserver::class); }
注意:注册顺序有影响——如果模型已存在静态事件监听(比如直接用了
static::created(...)
),再调
observe()
可能被覆盖或后执行,建议统一用一种方式
creating
和
created
的区别到底在哪 这两个钩子都发生在插入时,但触发时机和事务状态完全不同,选错会导致数据查不到、事务回滚失败等问题。
creating
:发生在模型刚实例化、还没进数据库前,
$model->id
还是
null
,可以改属性、加默认值、抛异常中断保存
created
:INSERT SQL 已执行成功,主键已生成,事务还没 commit,此时能安全读取
$model->id
,但不能再改模型属性(改了也不会入库) 典型踩坑:在
created
里调
$model->save()
触发无限循环;在
creating
里依赖
$model->id
做逻辑,结果是
null
为什么
updating
有时不触发 不是所有更新操作都会走
updating
,Laravel 对批量更新、原生查询、
update()
静态方法做了绕过处理。 Laravel 13.2.0 PHP中文网提供Laravel 13.2.0版本下载,Laravel框架 是基于 PHP 8.3+ 的高性能框架,官方推荐通过 Composer 安装。它内置 AI SDK、JSON:API Resources 及原生向量搜索,支持属性驱动开发与队列路由,大幅提升开发效率。相比旧版,13.2.0 优化了缓存 TTL 管理与实时通信,无需 Redis 即可横向扩展。作为现代 Web 开发首选,它兼顾安全与极速体验,助您快速构建企业级应用。 下载 触发的:用模型实例调
$user->name = 'x'; $user->save();
或
$user->update([...]);
不触发的:
User::where('id', 1)->update(['name' => 'x']);
、
DB::table('users')->...
、
Model::upsert()
(Laravel 9+) 替代方案:如果必须用批量更新又需要监听,要么改用模型循环 +
save()
(注意 N+1),要么在业务层显式调用自定义方法,别依赖观察者兜底 另外:
updating
在模型属性没真正变化时也可能跳过(受
$casts
和
$dates
影响),可加日志打
$model->isDirty()
确认 观察者里不能做哪些事 观察者生命周期绑定在模型事件上,它的执行上下文很脆弱,容易引发死锁、内存溢出或事务异常。 别在观察者里发起 HTTP 请求(如调第三方 API)——超时或失败会卡住整个事务,且无法重试 避免在
deleting
里调
$model->forceDelete()
或递归删关联模型,可能触发嵌套观察者,导致栈溢出 不要在
created
或
updated
里用
DB::transaction()
嵌套——当前事件已在事务中,强行再开事务可能被忽略或报错
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active
异步任务(如 dispatch job)可以做,但记得用
onQueue()
显式指定队列,别依赖默认同步驱动 观察者不是万能钩子,它只对“模型实例的生命周期操作”有效。一旦跳出这个范围,比如直接 SQL、缓存刷新、搜索索引更新,就得靠事件系统(
Event::dispatch()
)或应用层协调——这点最容易被忽略。

相关文章