本文目录导读:

在Laravel中,模型事件(Model Events)是Eloquent提供的强大特性,允许你在模型生命周期的特定时刻执行代码,以下是各种模型事件的触发时机详细介绍:
事件类型与触发时机
创建(creating/created)
// creating:创建前 // created:创建后(已保存到数据库) $user = new User; $user->name = 'John'; $user->created_at = now(); // creating触发 $user->save(); // created触发
更新(updating/updated)
// updating:更新前
// updated:更新后
$user = User::find(1);
$user->name = 'Jane';
$user->save(); // updating和updated都会触发
// 注意:批量更新不会触发
User::where('status', 1)->update(['status' => 0]);
保存(saving/saved)
// saving:创建或更新前(先于creating/updating) // saved:创建或更新后(后于created/updated) $user = new User; $user->name = 'Test'; $user->save(); // 顺序:saving → creating → created → saved $user->email = 'new@email.com'; $user->save(); // 顺序:saving → updating → updated → saved
删除(deleting/deleted)
// deleting:删除前 // deleted:删除后 $user = User::find(1); $user->delete(); // deleting和deleted都会触发 // 软删除也会触发 $user->delete(); // 如果是SoftDeletes,也会触发
恢复(restoring/restored)
// restoring:恢复前 // restored:恢复后 // 仅适用于软删除模型 $user = User::withTrashed()->find(1); $user->restore(); // restoring和restored都会触发
强制删除(forceDeleting/forceDeleted)
// forceDeleting:强制删除前 // forceDeleted:强制删除后 $user = User::withTrashed()->find(1); $user->forceDelete(); // forceDeleting和forceDeleted都会触发
事件监听方式
在模型类中直接定义
class User extends Model
{
protected static function booted()
{
static::creating(function ($user) {
if (empty($user->uuid)) {
$user->uuid = Str::uuid();
}
});
static::updating(function ($user) {
$user->updated_by = auth()->id();
});
static::deleted(function ($user) {
// 删除关联数据
Log::info("User {$user->id} deleted");
});
}
}
独立事件类
// app/Events/UserCreated.php
class UserCreated
{
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
}
// 在模型中使用
protected static function booted()
{
static::created(function ($user) {
event(new UserCreated($user));
});
}
// EventServiceProvider.php
protected $listen = [
UserCreated::class => [
SendWelcomeEmail::class,
CreateUserProfile::class,
],
];
观察者模式
// app/Observers/UserObserver.php
class UserObserver
{
public function creating(User $user)
{
$user->uuid = Str::uuid();
}
public function created(User $user)
{
// 创建后逻辑
}
public function updating(User $user)
{
// 更新前逻辑
}
public function updated(User $user)
{
// 更新后逻辑
}
public function saving(User $user) {}
public function saved(User $user) {}
public function deleting(User $user) {}
public function deleted(User $user) {}
public function restoring(User $user) {}
public function restored(User $user) {}
public function forceDeleting(User $user) {}
public function forceDeleted(User $user) {}
}
// AppServiceProvider.php
public function boot()
{
User::observe(UserObserver::class);
}
注意事项和陷阱
不会触发事件的操作
// ① 批量更新
User::where('age', '>', 18)->update(['status' => 2]);
// ② 直接使用DB
DB::table('users')->where('id', 1)->update(['name' => 'John']);
// ③ 复制的模型
$newUser = $existingUser->replicate();
$newUser->save(); // 只触发创建事件
// ④ forceFill + save 需要配合检查
$user->forceFill(['name' => 'John'])->save(); // 会触发保存事件
事件顺序
$user = User::create([...]); // 实际执行顺序: // 1. saving // 2. creating // 3. created // 4. saved $user->update([...]); // 实际执行顺序: // 1. saving // 2. updating // 3. updated // 4. saved
防止无限递归
// 在update中重复save会导致无限递归
static::updating(function ($user) {
// ❌ 错误:这样会无限递归
$user->name = strtoupper($user->name);
$user->save();
// ✅ 正确:直接修改属性,不需要再次save
$user->name = strtoupper($user->name);
});
条件判断
static::updating(function ($user) {
// 只在字段变更时执行
if ($user->isDirty('password')) {
// 密码变更了
}
// 检查原始值
if ($user->getOriginal('status') == 1 && $user->status == 2) {
// 状态从1变为2
}
});
实际应用示例
class Order extends Model
{
protected static function booted()
{
// 生成订单号
static::creating(function ($order) {
$order->order_no = 'ORD-' . date('YmdHis') . rand(1000, 9999);
});
// 更新库存
static::created(function ($order) {
foreach ($order->items as $item) {
Product::where('id', $item->product_id)
->decrement('stock', $item->quantity);
}
});
// 记录操作日志
static::updated(function ($order) {
Log::info('Order updated', [
'order_id' => $order->id,
'changes' => $order->getChanges()
]);
});
// 取消订单时恢复库存
static::deleting(function ($order) {
if ($order->status == OrderStatus::CANCELLED) {
Log::warning('Deleting order with status cancelled');
}
});
}
}
理解这些触发时机对于正确使用Laravel的事件系统至关重要,有助于你写出更健壮的业务逻辑。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播