Laravel 使用 事件和监听器实现 数据状态变更

首先知道事件是什么

1.事件的概念

事件(Event)是 Laravel 中实现观察者模式 的一种机制,它允许应用程序中的不同部分进行松耦合的通信。

通俗一点就是,发生在应用程序中的动作或者事情。例如:

  1. 用户注册成功后,需要发邮件,发短信,初始化数据;
  2. 订单支付成功后,库存处理,消息发送,订单处理;
  3. 文章发布成功后,用户的积分,通知审核者,推送阅读者;
  4. 。。。。

类似以上这些动作或事情,都可以看着一个个单独的事件。

2.事件组成部分

  1. 事件类(Event):承载事件相关数据的对象

  2. 事件触发:在代码中明确触发事件的位置

  3. 监听器(Listener):响应事件并执行处理的类

3.怎么工作

触发事件 -> 创建事件对象 -> 事件分发器 -> 匹配监听器 -> 执行监听器逻辑

4.事件特点

  1. 解耦性:将某些动作和主体功能的逻辑拆分,例如将用户注册和发邮件拆分开,用户注册后,直接触发邮件事件。根本不需要知道怎么发邮件的。两个互不影响。
  2. 可扩展性:一个事件支持多个监听器,例如用户注册成功后,原有一个监听器去发邮件,如果现在有个发短信的需求,直接添加一个新的监听器即可,不需要去修改原有的代码。减少出错率
  3. 队列支持:监听器可以同步执行,也可以异步执行。例如发邮件,处理大量的耗时任务,可以直接在异步里面执行,不影响主体功能

数据状态变更 事件开发

1.创建事件

使用 Artisan 命令创建一个新事件:

php 复制代码
php artisan make:event MyCustomState

app/Events 目录下会自动生成一个事件类。编辑一下

php 复制代码
<?php

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class MyCustomState
{
    use Dispatchable, SerializesModels;

    public $data;

    /**
     * 创建一个新的事件实例
     *
     * @param mixed $data 需要传递的数据
     * @return void
     */
    public function __construct($data)
    {
        $this->data = $data;
    }
}

__construct里面进行赋值处理 $this->data = $data;

2.创建监听器

使用命令行创建监听器

php 复制代码
 php artisan make:listener ProcessMyCustomState --event=MyCustomState

编辑监听器文件 app/Listeners/ProcessMyCustomState .php:

注意,处理这个事件的逻辑就在监听器里面实现。例如发短信,发邮件,等等

php 复制代码
<?php

namespace App\Listeners;

use App\Events\MyCustomState;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class ProcessMyCustomState 
{
    /**
     * 处理事件
     *
     * @param MyCustomEvent $event
     * @return void
     */
    public function handle(MyCustomState $event)
    {
       //接收事件的数据
        $data = $event->data;
        
        // 例如:记录日志、发送邮件、处理数据等
        \Log::info('事件已处理,数据:', ['data' => $data]);
        
        // 自我表现的时候到了,开始肆无忌惮的搭建屎山工程
        // ........
    }
}

3.注册事件和监听器

目前事件和监听器是两个独立的类,接下来要让监听器监听事件。也就是所谓的注册对应关系

编辑 app/Providers/EventServiceProvider.php 添加以下代码

php 复制代码
protected $listen = [
    MyCustomState::class => [
        ProcessMyCustomState::class,
    ],
];

请注意

MyCustomState::class 对应的是一个数组,也就是里面可以有多个监听器,即多个监听器监听一个事件

例如发短信,发邮件,等等。每个独立实现可以为一个监听器

这样就建立关系了。接下来只需要去触发这个事件即可

4.在控制器中触发事件

编辑一个控制器文件

php 复制代码
<?php

namespace App\Http\Controllers;

use App\Events\MyCustomEvent;
use Illuminate\Http\Request;

class MyController extends Controller
{
    public function triggerEvent(Request $request)
    {
        // 一些业务逻辑...
        $eventData = [
            'user_id' => auth()->id(),
            'action' => 'custom_action',
            'timestamp' => now(),
        ];
        
        // 触发事件
        event(new MyCustomState($eventData));
        
        // 或者也可以使用辅助函数
        // MyCustomState::dispatch($eventData);
        
        return response()->json(['message' => '事件已触发']);
    }
}

可以用 event(new MyCustomState($eventData)); 或者 MyCustomState::dispatch($eventData); 触发事件

以上就是正常一个事件的开发流程了。

如果监听器的逻辑较为复杂或者非常耗时,那么建议这个监听器进行异步执行。可以让监听器实现 ShouldQueue 接口

5.监听器队列处理(视情况而定)

简单说一下,什么情况使用队列监听器

  1. 耗时操作:发送邮件、生成报表、处理图片等

  2. 第三方API调用:支付网关、短信服务等

  3. 非关键操作:日志记录、数据分析等不需要即时完成的操作

  4. 高流量场景:需要快速响应用户而不等待后台处理完成

监听器实现 ShouldQueue 接口
php 复制代码
use Illuminate\Contracts\Queue\ShouldQueue;

class ProcessMyCustomState implements ShouldQueue
{
    use InteractsWithQueue;
    
    // 指定队列连接
    public $connection = 'ProcessMyCustomStateQueue';
    
    // 指定队列名称
    public $queue = 'emails';
    
    // 延迟处理(秒)
    public $delay = 60;
    
    // 最大尝试次数
    public $tries = 3;
    
    // 超时时间(秒)
    public $timeout = 30;
    
    public function handle(MyCustomEvent $event)
    {
       // 处理事件逻辑
        $data = $event->data;
        
        // 例如:记录日志、发送邮件、处理数据等
        \Log::info('事件已处理,数据:', ['data' => $data]);
        
        // 此处就是异步处理的逻辑
        // .....
    }
}
运行队列进程

如果使用队列,那么就必须运行队列的进程,这样才能及时处理到监听器的逻辑。

如果对队列不熟悉的同学,我后面会写一篇关于队列的文章,让大家学习一下

命令行启动队列

php 复制代码
php artisan queue:work  --queue=ProcessMyCustomStateQueue

启动后,当事件触发时,命令行会显示进程处理日志

总结

这就是在 Laravel 中实现事件和监听器的完整流程。

这种模式有助于解耦代码,使得业务逻辑更加清晰,也便于后期维护和扩展。

你可以根据需要创建多个监听器来监听同一个事件,或者为事件添加更多的属性和方法。

相关推荐
2401_890665861 小时前
免费送源码:Java+ssm+MySQL 基于PHP在线考试系统的设计与实现 计算机毕业设计原创定制
java·hadoop·spring boot·python·mysql·spring cloud·php
86Eric14 小时前
Laravel 实现 队列 发送邮件功能
php·laravel·队列·异步执行
亿坊电商19 小时前
PHP + Go 如何协同打造高并发微服务?
微服务·golang·php
左灯右行的爱情20 小时前
计算机网络-传输层基础概念
网络·计算机网络·php
SlientICE1 天前
预防WIFI攻击,保证网络安全
网络·安全·php
Sun7581 天前
Dcat-admin 轮播图组件
php
PeakXin1 天前
🚀 Windows 下实现 PHP 多版本动态切换管理(适配 phpStudy)+ 一键切换工具源码分享
php
ALe要立志成为web糕手1 天前
PHP反序列化
web安全·网络安全·php·反序列化
hello_simon1 天前
小白工具视频转gif,支持在线gif或视频互转,批量转换,免费在线使用,无需下载
开发语言·php·音视频
友善的猴子2 天前
JetBrains PhpStorm v2024.3.1 Mac PHP开发工具
macos·php·phpstorm