下面是一個完整的用戶注冊事件和監聽器的實現示例,包含事件、監聽器、注冊、觸發等完整流程。
一、軟件版本
- 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', '注冊成功!');}
}