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

相关推荐
BingoGo3 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack3 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack1 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo1 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
BingoGo2 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·laravel
JaguarJack2 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理3 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082853 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe3 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5
longxiangam3 天前
Composer 私有仓库搭建
php·composer