Laravel - 事件处理
Laravel - 事件和监听器 (Events and Listeners)
Section titled “Laravel - 事件和监听器 (Events and Listeners)”Laravel 的事件(events)提供了简单的观察者模式(observer pattern)实现,允许您订阅和监听应用程序中发生的各种事件。事件是解耦应用程序各个方面的绝佳方式,因为单个事件可以有多个相互独立的监听器(listeners)。
事件和监听器的工作流程
Section titled “事件和监听器的工作流程”通常的工作流程包括以下步骤:
- 定义事件类(Event Class): 创建一个表示事件的类。这个类通常包含与事件相关的数据。
- 定义监听器类(Listener Class(es)): 创建一个或多个监听器类,它们将在事件被调度(dispatched)后处理该事件。
- 注册事件和监听器: 在
EventServiceProvider中将事件映射到其对应的监听器。 - 调度事件(Dispatch an Event): 在您的应用程序代码中的某个地方触发该事件。
步骤 1:创建一个事件类
Section titled “步骤 1:创建一个事件类”您可以使用 Artisan CLI 命令生成一个新的事件类:
php artisan make:event PodcastProcessed此命令将创建一个新文件,例如 app/Events/PodcastProcessed.php。事件类通常是一个简单的数据容器。例如,我们的 PodcastProcessed 事件可能包含已处理的播客的 Eloquent 模型:
namespace App\Events;
use App\Models\Podcast; // 假设您有一个 Podcast 模型use Illuminate\Broadcasting\InteractsWithSockets;use Illuminate\Foundation\Events\Dispatchable;use Illuminate\Queue\SerializesModels;
class PodcastProcessed{ use Dispatchable, InteractsWithSockets, SerializesModels;
public Podcast $podcast;
/** * 创建一个新的事件实例。 * * @param \App\Models\Podcast $podcast * @return void */ public function __construct(Podcast $podcast) { $this->podcast = $podcast; }}注意:SerializesModels trait 将优雅地序列化(serialize)任何 Eloquent 模型,如果事件对象被序列化的话,例如在使用队列监听器(queued listeners)时。Dispatchable trait 允许轻松调度事件。
步骤 2:创建监听器类
Section titled “步骤 2:创建监听器类”接下来,您需要一个或多个监听器来处理该事件。您可以使用 Artisan 命令生成一个监听器:
php artisan make:listener SendPodcastNotification --event=PodcastProcessed这将创建 app/Listeners/SendPodcastNotification.php。--event 选项将在监听器的 handle 方法中对 PodcastProcessed 事件进行类型提示(type-hint)。在 handle 方法内部,您可以执行对事件做出响应的操作。
namespace App\Listeners;
use App\Events\PodcastProcessed;use Illuminate\Contracts\Queue\ShouldQueue; // 可选:用于队列监听器use Illuminate\Queue\InteractsWithQueue; // 可选:用于队列监听器// use Illuminate\Support\Facades\Mail; // 示例用法
class SendPodcastNotification // implements ShouldQueue // 可选{ // use InteractsWithQueue; // 可选
/** * 创建事件监听器。 * * @return void */ public function __construct() { // }
/** * 处理事件。 * * @param \App\Events\PodcastProcessed $event * @return void */ public function handle(PodcastProcessed $event) { // 访问事件中的播客: $event->podcast // 例如,发送电子邮件通知: // Mail::to($event->podcast->user_email)->send(new PodcastReadyNotification($event->podcast));
logger('Podcast processed: ' . $event->podcast->title); }}监听器也可以通过实现 ShouldQueue 接口来排队。这对于可以在后台执行的任务很有用。
步骤 3:注册事件和监听器
Section titled “步骤 3:注册事件和监听器”EventServiceProvider(位于 app/Providers/EventServiceProvider.php)是您注册事件监听器的地方。它包含一个 $listen 数组属性,用于将事件映射到其监听器。
namespace App\Providers;
use App\Events\PodcastProcessed;use App\Listeners\SendPodcastNotification;use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;// use Illuminate\Support\Facades\Event; // 简单使用 $listen 数组时不需要
class EventServiceProvider extends ServiceProvider{ /** * 应用程序的事件到监听器的映射。 * * @var array<class-string, array<int, class-string>> */ protected $listen = [ PodcastProcessed::class => [ SendPodcastNotification::class, // 您可以在此处为同一事件添加更多监听器 // 例如: App\Listeners\UpdatePodcastAnalytics::class, ], // 其他事件及其监听器... ];
/** * 为您的应用程序注册任何事件。 * * @return void */ public function boot() { // }
/** * 确定是否应自动发现事件和监听器。 * * @return bool */ public function shouldDiscoverEvents() { return false; // 如果偏好自动发现,设置为 true }}如果您使用 --event 选项生成了监听器,Laravel 可能已经为您添加了此映射。否则,将您的事件及其监听器添加到 $listen 数组中。
步骤 4:调度事件
Section titled “步骤 4:调度事件”要调度(dispatch)事件,您可以使用 event 辅助函数或 Event Facade 的 dispatch 方法。通常,您会在某个操作完成后调度事件。
// 控制器或服务中的示例use App\Events\PodcastProcessed;use App\Models\Podcast; // 假设您有一个 Podcast 模型
// ... 在您的代码中,在播客处理后 ...$podcast = Podcast::find(1);if ($podcast) { // 使用 event 辅助函数 event(new PodcastProcessed($podcast));
// 或者,如果您的事件类使用了 Dispatchable trait: // PodcastProcessed::dispatch($podcast);}当事件被调度时,Laravel 将调用该事件所有注册监听器的 handle 方法,并将事件实例传递给它们。
示例场景:新用户注册
Section titled “示例场景:新用户注册”让我们考虑一个常见的场景:当新用户注册时发送欢迎邮件。
-
事件(Event):
UserRegistered(例如:php artisan make:event UserRegistered)。此事件将携带User模型。app/Events/UserRegistered.php namespace App\Events;use App\Models\User;use Illuminate\Foundation\Events\Dispatchable;use Illuminate\Queue\SerializesModels;class UserRegistered{use Dispatchable, SerializesModels;public User $user;public function __construct(User $user) { $this->user = $user; }} -
监听器(Listener):
SendWelcomeEmail(例如:php artisan make:listener SendWelcomeEmail --event=UserRegistered)。此监听器将使用 Laravel 的 Mail 功能。app/Listeners/SendWelcomeEmail.php namespace App\Listeners;use App\Events\UserRegistered;use Illuminate\Support\Facades\Mail;use App\Mail\WelcomeMail; // 假设您创建了一个 Mailable: php artisan make:mail WelcomeMailclass SendWelcomeEmail{public function handle(UserRegistered $event){Mail::to($event->user->email)->send(new WelcomeMail($event->user));}} -
注册: 将
UserRegistered::class => [SendWelcomeEmail::class]添加到EventServiceProvider.php中的$listen。 -
调度: 在您的用户注册控制器中,成功创建用户后:
// 在您的 Auth Controller 或 Registration Service 中use App\Events\UserRegistered;use App\Models\User;// ...$user = User::create($validatedData);event(new UserRegistered($user));// 或者 UserRegistered::dispatch($user);// ...
此设置确保无论何时注册新用户并调度 UserRegistered 事件,SendWelcomeEmail 监听器都会自动被调用以发送欢迎邮件。这将发送邮件的逻辑与注册过程本身解耦。
事件和监听器是构建健壮、可维护和可扩展的 Laravel 应用程序的强大工具。有关更高级的主题,例如事件订阅者(event subscribers)、队列监听器和广播事件(broadcasting events),请查阅官方 Laravel 文档。