比如在用户注册时候需要一些额外的操作。
使用laravel中的事件系统去创建事件和监控器去实现便于开发和维护。
文档介绍 https://learnku.com/docs/laravel/8.x/events/9391#01e998
创建事件和监控器
#指令创建事件
php artisan make:event UserRegistered
#指令创建监控器
php artisan make:listener CreateUserDatabase --event=UserRegistered
事件案例代码:
<?php
namespace App\Events;
class UserRegistered
{
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public int $userId)
{
//Log::debug('UserRegistered注册事件');
}
}
监控案例代码:
<?php
namespace App\Listeners;
use App\Events\UserRegistered;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
class CreateUserDatabase implements ShouldQueue
{
/**
* 任务将被发送到的队列的名称
*
* @var string|null
*/
public $queue = 'listeners';
/**
* Create the event listener.
*
* @return void
*/
// public function __construct(){}
/**
* Handle the event.
*
* @param \App\Events\UserRegistered $event
* @return void
*/
public function handle(UserRegistered $event)
{
Log::debug('触发了用户注册事件 USER_ID: ' . $event->userId);
DB::table('users')->where('id', $event->userId)->update(['deleted_at' => time()]);
try {
DB::beginTransaction();
#创建新用户专属数据库
// DB::select('select * from users where active = ?', [1]); #执行sql原生操作
#创建上报字段信息表
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
}
}
/**
* 获取监听器队列的名称
*
* @return string
*/
// public function viaQueue()
// {
// return $this->queue;
// }
}
配置事件与监听器的绑定
打开 app/Providers/EventServiceProvider.php
文件。
protected $listen = [
UserRegistered::class => [
CreateUserDatabase::class,
],
];
使用事件
在想要触发的位置去进行触发事件的监听
use App\Events\UserRegistered;
//注册
public function register(Request $request)
{
$input = $request->only('account_name', 'password');
event(new UserRegistered(2)); #2为传递的用户ID
return $this->services->register($input);
}
事件执行方式
事件执行有两种方式
方式一,同步触发(同步执行)
这是最直接的触发方式,事件在触发后,相应的监听器会立即执行,执行过程与触发事件的代码在同一请求生命周期内完成。
同步触发适用于那些执行速度较快、不影响用户体验的操作。
同步触发事件的典型代码示例如下:
use App\Events\SomeEvent;
// 触发事件
event(new SomeEvent($data));
方式二,异步触发(队列方式)
对于耗时较长的事件处理逻辑,如发送邮件、短信通知、复杂的数据处理等,
推荐使用异步触发方式,以避免阻塞用户的请求响应。
Laravel 提供了队列(Queue)系统来实现异步处理。
异步触发事件通常有两种模式:
- 使用 Queueable 特性
在事件类中使用 Illuminate\Queue\InteractsWithQueue 特性,并实现
shouldQueue 方法,使事件变为可队列化的。然后,当触发该事件时,Laravel 会自动将其推送到队列中异步处理。
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SomeEvent implements ShouldQueue
{
use Dispatchable, InteractsWithQueue;
// ...构造函数和属性...
public function handle()
{
// 事件处理逻辑
}
}
- 在监听器中使用队列
即使事件本身没有实现 ShouldQueue 接口,也可以在监听器的 handle 方法中将耗时操作放入队列。
这要求监听器实现 ShouldQueue 接口,并配置监听器为异步处理。
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SomeEventListener implements ShouldQueue
{
use InteractsWithQueue;
public function handle(SomeEvent $event)
{
// 将耗时操作放入队列处理
SomeLongRunningJob::dispatch($event->data);
}
}
触发队列任务
在上述异步处理方式中,提到的 SomeLongRunningJob 是一个队列任务的例子。
你可以使用 Laravel 的任务调度器(Jobs)配合队列来进一步处理复杂的异步逻辑。
创建队列任务并将其加入队列的代码示例如下:
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\Jobs\Job;
use Illuminate\Contracts\Queue\ShouldQueue;
class SomeLongRunningJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, SerializesModels;
public $data;
public function __construct($data)
{
$this->data = $data;
}
public function handle()
{
// 执行耗时任务
}
}
// 触发队列任务
SomeLongRunningJob::dispatch($data);
总结
Laravel 提供了灵活的事件触发机制,无论是同步还是异步处理,都能通过简洁的API实现复杂逻辑的解耦和高效执行。
评论