Tách rời Logic với Laravel Events và Listeners
Hệ thống Event của Laravel cung cấp một triển khai observer đơn giản, cho phép bạn đăng ký và lắng nghe các event khác nhau trong ứng dụng. Điều này hoàn hảo để tách rời các khía cạnh khác nhau của logic ứng dụng.
Vấn đề: Tight Coupling
Hãy tưởng tượng một phương thức lưu trữ đăng ký người dùng:
public function store(Request $request) {
$user = User::create($request->validated());
// Gửi email
Mail::to($user)->send(new WelcomeEmail($user));
// Logging
Log::info("User registered: " . $user->id);
// Đăng ký newsletter
Newsletter::subscribe($user->email);
return redirect('/home');
}
Controller này xử lý quá nhiều trách nhiệm. Nếu việc gửi email thất bại, hoặc logic thay đổi, bạn phải sửa controller.
Giải pháp: Events
1. Tạo Event
php artisan make:event UserRegistered
Truyền dữ liệu (User) vào event:
class UserRegistered
{
use Dispatchable, SerializesModels;
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
}
2. Tạo Listeners
Tạo listeners cho mỗi hành động riêng biệt:
php artisan make:listener SendWelcomeEmail --event=UserRegistered
php artisan make:listener SubscribeToNewsletter --event=UserRegistered
Ví dụ Listener SendWelcomeEmail:
public function handle(UserRegistered $event)
{
Mail::to($event->user)->send(new WelcomeEmail($event->user));
}
3. Đăng ký Events & Listeners
Trong môi trường local, Laravel có thể tự động phát hiện listeners. Hoặc bạn có thể đăng ký rõ ràng trong EventServiceProvider (hoặc AppServiceProvider trong Laravel 11+):
Event::listen(
UserRegistered::class,
[SendWelcomeEmail::class, 'handle']
);
Event::listen(
UserRegistered::class,
[SubscribeToNewsletter::class, 'handle']
);
4. Phát Event
Bây giờ controller của bạn trở nên sạch sẽ:
public function store(Request $request) {
$user = User::create($request->validated());
UserRegistered::dispatch($user);
return redirect('/home');
}
Queued Listeners
Nếu việc gửi email chậm, bạn có thể queue listener ngay lập tức bằng cách thêm interface ShouldQueue:
use Illuminate\Contracts\Queue\ShouldQueue;
class SendWelcomeEmail implements ShouldQueue
{
public function handle(UserRegistered $event)
{
// Bây giờ nó sẽ chạy trong background worker!
}
}
Events và Listeners làm cho ứng dụng của bạn dễ test, bảo trì và mở rộng hơn.