Laravel 事件与监听器

下面是一个完整的用户注册事件和监听器的实现示例,包含事件、监听器、注册、触发等完整流程。

一、软件版本

  • php: 8.2.20
  • laravel: 11
  • mysql: 8.0.29

二、完整实现过程

1.创建事件

1.1 首先创建用户注册事件

php artisan make:event UserRegistered

1.2 编辑app/Events/UserRegistered.php

<?php
namespace App\Events;use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;class UserRegistered
{use Dispatchable, InteractsWithSockets, SerializesModels;/*** 创建一个新的事件实例*/public function __construct(public User $user){}
}

2. 创建监听器

2.1 创建两个监听器:发送欢迎邮件记录注册日志

php artisan make:listener SendWelcomeEmail --event=UserRegistered
php artisan make:listener LogUserRegistration --event=UserRegistered

2.2 编辑 app/Listeners/SendWelcomeEmail.php

<?phpnamespace App\Listeners;use App\Events\UserRegistered;
use App\Mail\WelcomeEmail;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Mail;class SendWelcomeEmail implements ShouldQueue
{/*** 处理事件** @param UserRegistered $event* @return void*/public function handle(UserRegistered $event){Mail::to($event->user->email)->send(new WelcomeEmail($event->user));}/*** 处理失败的任务** @param UserRegistered $event* @param \Throwable $exception* @return void*/public function failed(UserRegistered $event, $exception){// 发送失败通知给管理员}
}

2.3 编辑 app/Listeners/LogUserRegistration.php

<?phpnamespace App\Listeners;use App\Events\UserRegistered;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;class LogUserRegistration
{/*** Create the event listener.*/public function __construct(){//}/*** Handle the event.*/public function handle(UserRegistered $event): void{Log::info('新用户注册完成: '.$event->user->email);}
}

3. 注册事件和监听器

3.1 创建 app/Providers/EventServiceProvider.php

php artisan make:provider EventServiceProvider

3.2 编辑 app/Providers/EventServiceProvider.php

<?phpnamespace App\Providers;use App\Events\UserRegistered;
use App\Listeners\LogUserRegistration;
use App\Listeners\SendWelcomeEmail;
use Illuminate\Support\ServiceProvider;class EventServiceProvider extends ServiceProvider
{/*** 事件与监听器的映射关系*/protected $listen = [UserRegistered::class => [SendWelcomeEmail::class,LogUserRegistration::class],];/*** Register services.*/public function register(): void{//}/*** Bootstrap services.* 注册任何其他事件*/public function boot(): void{//}
}

4. 创建邮件类

4.1 创建欢迎邮件模板

php artisan make:mail WelcomeEmail --markdown=emails.welcome

4.2 编辑 app/Mail/WelcomeEmail.php

<?phpnamespace App\Mail;use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;class WelcomeEmail extends Mailable
{use Queueable, SerializesModels;/*** 创建一个新的消息实例** @param User $user*/public function __construct(public User $user){}/*** 构建消息** @return $this*/public function build(){return $this->markdown('emails.welcome')->subject('欢迎加入我们的平台');}
}

4.2 编辑 resources/views/emails/welcome.blade.php

@component('mail::message')# 欢迎, {{ $user->name }}!感谢您注册我们的平台。您的账户已经成功创建。@component('mail::button', ['url' => url('/dashboard')])访问仪表盘@endcomponent谢谢,{{ config('app.name') }}
@endcomponent

4.3 邮件配置 .env

MAIL_MAILER=smtp
MAIL_SCHEME=null
MAIL_HOST=smtp.163.com
MAIL_PORT=465
MAIL_ENCRYPTION=ssl
MAIL_USERNAME=xxx@163.com
MAIL_PASSWORD=GTkCEsxxxxxxx
MAIL_FROM_ADDRESS="xxxx@163.com"
MAIL_FROM_NAME="${APP_NAME}"

5. 测试事件

5.1 创建测试

php artisan make:test UserRegistrationTest

5.2 编辑 tests/Feature/UserRegistrationTest.php

<?phpnamespace Tests\Feature;use App\Events\UserRegistered;
use App\Mail\WelcomeEmail;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;class UserRegistrationTest extends TestCase
{use RefreshDatabase;public function test_user_registration_dispatches_event(){Event::fake();$user = User::factory()->create();event(new UserRegistered($user));Event::assertDispatched(UserRegistered::class, function ($event) use ($user) {return $event->user->id === $user->id;});}public function test_welcome_email_is_sent(){Mail::fake();$user = User::factory()->create();event(new UserRegistered($user));Mail::assertSent(WelcomeEmail::class, function ($mail) use ($user) {return $mail->user->id === $user->id;});}
}

5.3 测试结果

在这里插入图片描述

6. 在控制器中触发事件

6.1 编辑 app/Http/Controllers/Auth/RegisterController.php

<?phpnamespace App\Http\Controllers\Auth;use App\Events\UserRegistered;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Support\Facades\Hash;class RegisterController extends Controller
{public function register(){// 验证逻辑...$user = User::create(['name' => request('name'),'email' => request('email'),'password' => Hash::make(request('password')),]);// 触发用户注册事件event(new UserRegistered($user));// 或者使用静态方法// UserRegistered::dispatch($user);return redirect('/home')->with('success', '注册成功!');}
}

7. 访问控制器后

7.1 laravel日志中显示

在这里插入图片描述

7.2 目标邮箱收到邮件

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93754.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93754.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端 React 实现数据懒加载-滚动触底加载数据

在 React 中使用 Intersection Observer API 实现触底加载分页&#xff08;无限滚动&#xff09;1.基本实现思路 在列表底部放置一个 哨兵元素&#xff08;Sentinel&#xff09;&#xff08;如 <div>&#xff09;。使用 IntersectionObserver 监听该元素是否进入视口&…

MySQL 50 道经典练习题及答案

目录 一、数据表设计与初始化 1. 数据表结构说明 2. 建表语句 3. 插入测试数据 二、练习题及答案 1. 查询 "01" 课程比 "02" 课程成绩高的学生的信息及课程分数 2. 查询同时存在 "01" 课程和 "02" 课程的情况 3. 查询存在 &qu…

电竞护航小程序搭建三角洲俱乐部护航派单小程序开发游戏派单系统定制开发

成品系统&#xff0c;可以快速搭建。功能概述&#xff1a;商家入驻、老板点单、快捷发单、自定义发单、发单列表、管事入驻、订单审核裁决、打手入驻、打手排行榜、邀请排行榜、账户充值、余额提现、成为客服等

MYSQL-增删查改CRUD

目录 &#x1f33f;前言&#xff1a; &#x1f33f;增-C-Create-新增 &#x1f9ca;单行数据全列插入 &#x1f34b;‍&#x1f7e9;语法&#xff1a; &#x1f34b;‍&#x1f7e9;演示&#xff1a; &#x1f9ca;指定列插入 &#x1f34b;‍&#x1f7e9;语法&#xf…

【Loss学习笔记】Focal loss、QFL、DFL、VFL——目标检测定位损失函数详解

文章目录Focal loss&#xff08;2018 ICCV &#xff0c;RetinaNet&#xff09;1、Focal Loss 提出背景问题一&#xff1a;正负样本数量不均衡问题问题二&#xff1a;难分类/易分类样本数量不均衡问题对两个问题的解决2、正负样本数量不均衡问题的解决&#xff1a;Focal loss 的…

nertctl使用了解

测试了几个容器&#xff0c;似乎未对k8s的containerd产生影响&#xff0c;都能访问 再次测试&#xff0c;containerd发生了重启&#xff0c;nrtdctl启动的容器都没了 #### sealos 创建containerd集群 sealos run registry.cn-shanghai.aliyuncs.com/labring/kubernetes:v1.29…

三、k8s 1.29 之 资源清单

一、什么是资源 资源(Resources) 是指集群中可被分配、管理和调度的各种实体,既包括计算、存储、网络等基础设施资源,也包括 K8s 自身定义的 API 对象(如 Pod、Deployment 等)。这些资源是 K8s 调度和管理工作负载的核心基础。 Kubernetes 中的资源本质上是 “可被操作的…

React中常用的Hook(useEffect、useRef、useMemo、useNavigate、useParams)

React hook1&#xff1a;useEffect 在编程中&#xff0c;副作用是指函数或表达式在执行过程中对外部环境产生影响的行为。例如&#xff1a; 修改外部变量&#xff08;如全局变量、DOM、API 请求、设置定时器等&#xff09; 什么是纯函数&#xff1f; // 纯函数&#xff1a;输入…

关联规则挖掘1:Apriori算法

目录 一、Apriori算法核心原理 1. 基本概念 2. Apriori性质 二、完整案例计算&#xff08;超市购物数据&#xff09; ​步骤1&#xff1a;按字母序重排每笔交易​ ​步骤2&#xff1a;统计频繁1-项集&#xff08;min_support40%&#xff09;​​ ​步骤3&#xff1a;生成…

基于 C++ 线程池的多线程目标检测后处理系统设计与实现

在实际的智能视频分析系统中,目标检测(如 YOLOv5)只是第一步。检测结果往往需要进行后续处理:画框、报警、推流、日志记录等。这些操作如果在检测主线程中同步执行,会严重拖慢整体推理速度。 本文将带你从零实现一个基于 C++ 模板线程池的异步后处理系统,实现“检测与后…

Java并发容器详解

1. JUC并发容器概述 Java集合容器框架主要有四大类别&#xff1a;List、Set、Queue、Map。常见的ArrayList、LinkedList、HashMap等容器都是非线程安全的。 Java提供了同步容器&#xff08;如Vector、Hashtable、SynchronizedList&#xff09;通过synchronized实现同步&#xf…

SpringAI系列---【SpringA集成OllamaI如何先调用向量库,再把查到的结果一起传给大模型?】

SpringAI如何先调用向量库&#xff0c;再把查到的结果一起传给大模型&#xff1f; 1.引入pom <dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-ollama</artifactId></depend…

告别“测试滞后”:AI实时测试工具在敏捷开发中的落地经验

告别“测试滞后”&#xff1a;AI实时测试工具在敏捷开发中的落地经验 在敏捷开发的“快速迭代”节奏中&#xff0c;测试环节常常成为“拖后腿”的短板。某互联网公司的敏捷团队曾陷入这样的循环&#xff1a;2周迭代周期中&#xff0c;开发用10天完成功能&#xff0c;留给测试的…

K8S-Pod资源对象

一、K8S架构与组件1、K8S架构k8s 总体架构采用了经典的 maste/slave 架构模式&#xff0c;分 master 节点和 worker 节点&#xff0c;节点可以是虚拟机也可以是物理机。K8S组件 master 节点组件Kube-apiserver 用于暴露 Kubernetes API&#xff0c;任何资源请求或调用操作都是通…

PyTorch API 5

文章目录torch.compiler延伸阅读torch.fft快速傅里叶变换辅助函数torch.func什么是可组合的函数变换&#xff1f;为什么需要可组合的函数变换&#xff1f;延伸阅读torch.futurestorch.fx概述编写转换函数图结构快速入门图操作直接操作计算图使用 replace_pattern() 进行子图重写…

基于决策树模型的汽车价格预测分析

一、整体流程概览这份代码实现了一个完整的机器学习预测流程&#xff0c;核心目标是通过汽车的各项特征预测其价格。整体流程分为 6 个主要步骤&#xff1a;模拟生成汽车数据集&#xff08;含价格标签&#xff09;数据预处理&#xff08;清洗、编码、特征选择&#xff09;探索性…

0基础安卓逆向原理与实践:第2章:编程基础与工具链

第2章:编程基础与工具链 2.1 Java编程基础 2.1.1 Java语言特性 Java是安卓应用开发的主要语言,具有以下核心特性: mindmaproot((Java特性))面向对象封装继承多态抽象平台无关字节码JVM一次编译到处运行内存管理自动垃圾回收堆栈管理引用类型安全性字节码验证安全管理器访…

深入理解JVM内存结构:从字节码执行到垃圾回收的全景解析

&#x1f9e0; 深入理解JVM内存结构&#xff1a;从字节码执行到垃圾回收的全景解析 #JVM内存模型 #Java性能优化 #垃圾回收机制 #并发编程一、JVM内存结构全景图二、线程共享区域详解 2.1 堆&#xff08;Heap&#xff09;—— 对象生存的宇宙 存储内容&#xff1a; 所有new创建…

用 C++ 构建高性能测试框架:从原型到生产实战指南

用 C 构建高性能测试框架&#xff1a;从原型到生产实战指南 ​C 测试框架的关键价值​&#xff1a;当你的测试需要每秒处理百万级交易&#xff0c;微秒级延迟要求已成为常态时&#xff0c;Python GC 的暂停便是不可接受的奢侈。 本文将深入探讨如何用 C 构建兼具灵活性和高性能…

【C语言16天强化训练】从基础入门到进阶:Day 4

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、洛谷刷题、C/C基础知识知识强化补充、C/C干货分享&学习过程记录 &#x1f349;学习方向&#xff1a;C/C方向 ⭐️人…