Laravel 13 事件系统详解

摘要

Laravel 的事件系统提供了观察者模式的实现,允许订阅和监听应用中的事件。本文将深入讲解 Laravel 13 的事件系统,包括:

  • 事件与监听器
  • 事件订阅者
  • 队列处理
  • 模型事件
  • 实战案例与最佳实践

本文适合希望掌握事件系统的 Laravel 开发者。

1. 创建事件与监听器

1.1 生成事件

1
php artisan make:event OrderShipped

1.2 事件类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\Order;

class OrderShipped
{
use Dispatchable, SerializesModels;

public function __construct(
public Order $order
) {}
}

1.3 生成监听器

1
php artisan make:listener SendShipmentNotification --event=OrderShipped

1.4 监听器类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

namespace App\Listeners;

use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendShipmentNotification implements ShouldQueue
{
public function handle(OrderShipped $event): void
{
// 发送通知
$event->order->user->notify(new OrderShippedNotification($event->order));
}
}

2. 注册事件

2.1 在 EventServiceProvider 注册

1
2
3
4
5
6
7
// app/Providers/EventServiceProvider.php
protected $listen = [
OrderShipped::class => [
SendShipmentNotification::class,
UpdateInventory::class,
],
];

2.2 自动发现

1
2
3
4
5
// config/app.php
'events' => [
'discover' => true,
'paths' => [app_path('Listeners')],
],

3. 分发事件

3.1 使用事件辅助函数

1
2
3
use App\Events\OrderShipped;

event(new OrderShipped($order));

3.2 使用事件静态方法

1
OrderShipped::dispatch($order);

4. 队列监听器

4.1 实现队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;

public function handle(OrderShipped $event): void
{
// 处理逻辑
}

public function failed(OrderShipped $event, Throwable $exception): void
{
// 失败处理
}
}

4.2 配置队列

1
2
3
4
5
6
7
class SendShipmentNotification implements ShouldQueue
{
public $queue = 'notifications';
public $delay = 60;
public $tries = 3;
public $backoff = [10, 30, 60];
}

5. 事件订阅者

5.1 创建订阅者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

namespace App\Listeners;

use Illuminate\Events\Dispatcher;

class UserEventSubscriber
{
public function handleUserCreated($event): void
{
// 处理用户创建
}

public function handleUserDeleted($event): void
{
// 处理用户删除
}

public function subscribe(Dispatcher $events): array
{
return [
UserCreated::class => 'handleUserCreated',
UserDeleted::class => 'handleUserDeleted',
];
}
}

5.2 注册订阅者

1
2
3
4
// app/Providers/EventServiceProvider.php
protected $subscribe = [
UserEventSubscriber::class,
];

6. 模型事件

6.1 模型事件监听

1
2
3
4
5
6
7
8
9
10
11
12
13
use App\Models\User;

User::created(function ($user) {
// 用户创建后
});

User::updated(function ($user) {
// 用户更新后
});

User::deleted(function ($user) {
// 用户删除后
});

6.2 在模型中定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class User extends Model
{
protected static function booted()
{
static::creating(function ($user) {
$user->api_token = Str::random(60);
});

static::updating(function ($user) {
if ($user->isDirty('email')) {
$user->email_verified_at = null;
}
});
}
}

7. 实战案例

7.1 订单处理事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\Order;

class OrderPlaced
{
use Dispatchable, SerializesModels;

public function __construct(
public Order $order
) {}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

namespace App\Listeners;

use App\Events\OrderPlaced;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Services\InventoryService;
use App\Notifications\OrderConfirmation;

class ProcessOrder implements ShouldQueue
{
public function __construct(
protected InventoryService $inventory
) {}

public function handle(OrderPlaced $event): void
{
$order = $event->order;

// 更新库存
$this->inventory->decrement($order);

// 发送确认邮件
$order->user->notify(new OrderConfirmation($order));

// 记录日志
Log::info('Order processed', ['order_id' => $order->id]);
}
}

8. 最佳实践

8.1 命名规范

1
2
3
4
5
6
7
8
9
// 推荐:过去时
OrderShipped
UserCreated
PaymentProcessed

// 不推荐
ShipOrder
CreateUser
ProcessPayment

8.2 使用队列

1
2
3
4
5
// 耗时操作使用队列
class SendNotification implements ShouldQueue
{
// ...
}

9. 总结

Laravel 的事件系统提供了强大的事件驱动能力:

  1. 解耦代码:事件与监听器分离
  2. 队列支持:异步处理事件
  3. 模型事件:自动触发模型事件
  4. 订阅者:批量订阅事件

参考资料