下面是一个完整的用户注册事件和监听器的实现示例,包含事件、监听器、注册、触发等完整流程。
一、软件版本
- 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', '注册成功!');}
}