本文目录导读:

在 PHP 中,模型事件主要与 ORM(对象关系映射)框架相关,最常见的框架是 Laravel Eloquent,我将以 Laravel 为例,详细介绍模型事件的使用方法。
什么是模型事件
模型事件是数据库模型生命周期中触发的钩子,允许你在特定时刻执行自定义逻辑,Eloquent 模型会自动触发这些事件。
常用事件列表
Eloquent 提供以下模型事件:
生命周期事件(按顺序)
// 创建过程 creating → created // 更新过程 updating → updated // 保存过程(创建+更新都会触发) saving → saved // 删除过程 deleting → deleted // 恢复软删除 restoring → restored // 查询过程 retrieving → retrieved
事件监听方式
模型内定义 $dispatchesEvents 属性
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $dispatchesEvents = [
'created' => UserCreated::class,
'deleted' => UserDeleted::class,
];
}
模型内使用静态方法
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected static function booted()
{
static::creating(function ($user) {
// 创建前触发
$user->status = 'active';
$user->remember_token = Str::random(20);
});
static::created(function ($user) {
// 创建后触发
Log::info('用户创建成功: ' . $user->email);
event(new UserCreated($user));
});
static::updating(function ($user) {
// 更新前触发
$user->updated_by = auth()->id();
});
static::deleted(function ($user) {
// 删除后触发
Mail::to($user->email)->send(new AccountDeletedMail());
});
static::retrieved(function ($user) {
// 查询后触发
$user->last_retrieved_at = now();
});
}
}
在服务提供者中注册
<?php
namespace App\Providers;
use App\Models\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
User::observe(UserObserver::class);
}
}
使用观察者(推荐)
观察者是组织事件监听代码的最佳方式:
<?php
namespace App\Observers;
use App\Models\User;
use Illuminate\Support\Facades\Log;
class UserObserver
{
public function creating(User $user)
{
// 生成唯一标识
$user->user_code = 'USR' . time() . rand(1000, 9999);
}
public function created(User $user)
{
// 发送欢迎通知
$user->notify(new WelcomeNotification());
// 记录日志
Log::info('用户创建: ' . $user->email);
// 创建关联数据
$user->profile()->create([
'bio' => '新用户'
]);
}
public function updating(User $user)
{
// 更新前检查
if ($user->isDirty('email')) {
$user->email_verified_at = null;
}
}
public function updated(User $user)
{
// 更新后的操作
activity()->log('用户信息已更新');
}
public function deleting(User $user)
{
// 防止删除管理员
if ($user->is_admin) {
return false; // 返回 false 可以阻止删除
}
}
public function deleted(User $user)
{
// 清理关联数据
$user->logs()->delete();
Storage::delete($user->avatar_path);
}
public function restored(User $user)
{
// 恢复软删除
$user->restore_notes = '用户申诉恢复';
}
}
事件的应用场景
自动填充字段
class Product extends Model
{
protected static function booted()
{
static::creating(function ($product) {
// 自动生成商品编号
$product->sku = strtoupper(uniqid('SKU-'));
// 设置默认库存
if (is_null($product->stock)) {
$product->stock = 0;
}
// 设置创建者
$product->created_by = auth()->user()->id ?? null;
});
static::updating(function ($product) {
// 自动更新修改者
$product->updated_by = auth()->user()->id ?? null;
});
}
}
数据关联处理
class Order extends Model
{
protected static function booted()
{
static::created(function ($order) {
// 创建订单后自动生成订单日志
$order->orderLogs()->create([
'action' => 'order_created',
'description' => '订单已创建',
'operator_id' => auth()->id()
]);
// 更新库存
foreach ($order->items as $item) {
$item->product->decrement('stock', $item->quantity);
}
});
static::updated(function ($order) {
// 订单状态变更时发送通知
if ($order->wasChanged('status')) {
$order->customer->notify(new OrderStatusUpdated($order));
$order->orderLogs()->create([
'action' => 'status_changed',
'description' => "状态变更为: {$order->status}",
'operator_id' => auth()->id()
]);
}
});
}
}
缓存管理
class Setting extends Model
{
protected static function booted()
{
static::saved(function ($setting) {
// 清除相关缓存
Cache::forget('setting.' . $setting->key);
Cache::forget('all_settings');
});
static::deleted(function ($setting) {
// 清除相关缓存
Cache::forget('setting.' . $setting->key);
Cache::forget('all_settings');
});
}
}
事件与队列结合
class User extends Model
{
protected static function booted()
{
static::created(function ($user) {
// 异步发送邮件
dispatch(function () use ($user) {
Mail::to($user->email)->send(new WelcomeMail($user));
})->delay(now()->addMinutes(10));
});
static::deleted(function ($user) {
// 异步清理资料
dispatch(new CleanUserDataJob($user->id))->onQueue('cleanup');
});
}
}
注意事项
事件中使用事务
class TransactionObserver
{
public function created(Transaction $transaction)
{
// 在事务中执行
DB::transaction(function () use ($transaction) {
// 更新余额
$transaction->account->balance += $transaction->amount;
$transaction->account->save();
// 记录变动
$transaction->account->transactions()->create([
'type' => 'balance_change',
'amount' => $transaction->amount
]);
});
}
}
阻止事件执行
class UserObserver
{
public function deleting(User $user)
{
// 返回 false 会阻止删除
if ($user->hasActiveOrders()) {
return false;
}
}
}
// 使用事件阻止
static::updating(function ($user) {
// 检查邮箱是否被占用
if (User::where('email', $user->email)->where('id', '!=', $user->id)->exists()) {
return false; // 阻止更新
}
});
调试事件
// 临时监听所有事件
Event::listen('eloquent.*: App\Models\User', function ($event, $data) {
Log::info('User model event fired: ' . $event);
});
事件类示例
<?php
namespace App\Events;
use App\Models\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class UserCreated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function broadcastOn()
{
return new Channel('users.' . $this->user->id);
}
}
最佳实践建议
- 事件命名要清晰:使用明确的事件名称,如
UserCreated、OrderPaid - 保持事件轻量:不要做过重的操作,大任务放到队列中
- 使用观察者组织:当有多个事件监听时,使用观察者类组织更清晰
- 避免递归触发:在事件中保存模型时,注意防止无限递归
通过合理使用模型事件,可以让代码更加解耦、易于维护,并且可以很方便地在模型生命周期中添加各种业务逻辑。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播