Laravel 事件与监听器

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

一、软件版本

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

二、完整实现过程

1.创建事件

1.1 首先创建用户注册事件

bash 复制代码
php artisan make:event UserRegistered

1.2 编辑app/Events/UserRegistered.php

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 创建两个监听器:发送欢迎邮件记录注册日志

bash 复制代码
php artisan make:listener SendWelcomeEmail --event=UserRegistered
php artisan make:listener LogUserRegistration --event=UserRegistered

2.2 编辑 app/Listeners/SendWelcomeEmail.php

php 复制代码
<?php

namespace 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

php 复制代码
<?php

namespace 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

bash 复制代码
php artisan make:provider EventServiceProvider

3.2 编辑 app/Providers/EventServiceProvider.php

php 复制代码
<?php

namespace 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 创建欢迎邮件模板

bash 复制代码
php artisan make:mail WelcomeEmail --markdown=emails.welcome

4.2 编辑 app/Mail/WelcomeEmail.php

php 复制代码
<?php

namespace 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

html 复制代码
@component('mail::message')
    # 欢迎, {{ $user->name }}!

    感谢您注册我们的平台。您的账户已经成功创建。

    @component('mail::button', ['url' => url('/dashboard')])
        访问仪表盘
    @endcomponent

    谢谢,
    {{ config('app.name') }}
@endcomponent

4.3 邮件配置 .env

bash 复制代码
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 创建测试

bash 复制代码
php artisan make:test UserRegistrationTest

5.2 编辑 tests/Feature/UserRegistrationTest.php

php 复制代码
<?php

namespace 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

php 复制代码
<?php

namespace 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 目标邮箱收到邮件

相关推荐
AI逐月2 小时前
tmux 常用命令总结:从入门到稳定使用的一篇实战博客
linux·服务器·ssh·php
学***54233 小时前
如何轻松避免网络负载过大
开发语言·网络·php
darkb1rd5 小时前
二、PHP 5.4-7.4版本演进与安全改进
安全·php·webshell
程序 代码狂人6 小时前
CentOS7初始化配置操作
linux·运维·开发语言·php
m0_748233176 小时前
PHP版本演进:从7.x到8.x全解析
java·开发语言·php
zhengfei6117 小时前
精选的优秀法证分析工具和资源列表
开发语言·php
REDcker7 小时前
RFC1918私有IP地址空间详解
网络协议·tcp/ip·php
云云只是个程序马喽9 小时前
AI短剧创作系统源码(PHP+MySQL+Uniapp)实现方案
php
Godspeed Zhao21 小时前
现代智能汽车系统——总线技术1
网络·汽车·php
stwood0071 天前
如何在 EC-CUBE 4 中为产品图像启用 WebP 格式图像
php