模型事件必须在模型类内部用static::created等静态方法注册,booted()执行一次适合注册全局监听器,booting()每次实例化前触发适合设默认值;creating/updating等“ing”事件可修改属性或中断保存,created/updated等“ed”事件数据已落库不可改;批量操作不触发事件;软删除的deleted事件中deleted_at为null需refresh获取。

模型事件不是靠门面注册的,Event 门面和模型生命周期事件完全无关——用错地方会收不到任何回调。
Model 的 booted 和 booting 怎么写才生效
模型事件绑定必须在模型类内部完成,靠静态 booted 方法或 booting 钩子。Laravel 不允许在外部用门面“监听”模型事件(比如 Event::listen('eloquent.created: App\Models\Post') 已废弃且不推荐)。
-
booted()在模型首次加载后执行一次,适合注册全局事件监听器 -
booting()在每次实例化前触发,适合做属性默认值、条件约束等 - 必须用
static::created、static::updated这类静态方法注册,不能用$this->created
示例:
class Post extends Model
{
protected static function booted()
{
static::created(function ($post) {
// 新建后触发
});
static::updating(function ($post) {
// 更新前触发(注意是 updating,不是 updated)
});
}
}
creating vs created:时机差半拍就存不到数据
带 ing 后缀的是「操作前」事件(如 creating、updating),可以修改模型属性甚至中断保存;带 ed 后缀的是「操作后」事件(如 created、updated),此时数据已落库,改 $model->xxx 没用。
-
creating中 return false 可取消保存,created中 return 无效 -
saving是唯一能同时拦截 create/update 的事件,适合统一处理字段(如 slug 生成) - 批量操作(
insert()、upsert())不触发任何模型事件
为什么 deleted 事件里查不到软删除字段?
软删除模型触发的是 deleting 和 deleted,但 deleted 触发时,deleted_at 已写入数据库,而模型实例的 $model->deleted_at 仍是 null —— 因为 Laravel 默认不会重新加载该字段。
- 想在
deleted里读取deleted_at,得手动刷新:$model->refresh()->deleted_at - 更稳妥的做法是在
deleting里取值,那时$model->deleted_at还是原始值(或 null) - 硬删除(
forceDelete())才真正走deleted,软删除其实走的是trashed事件(需单独监听)
模型事件本质是静态观察者,没有 IOC 容器介入,别试图在里面 resolve 服务或依赖注入;跨模型耦合逻辑建议抽到专门的 event listener 类里,否则调试时连调用栈都找不到源头。









