Ở bài trước, chúng ta đã học Observer.
Observer cho phép chúng ta phản ứng khi một Eloquent Model xảy ra sự kiện:
Post
│
├── created
├── updated
├── deleted
└── restored
│
▼
PostObserver
Ví dụ:
public function created(Post $post): void
{
logger("Post {$post->id} đã được tạo");
}
Observer rất hữu ích.
Tuy nhiên, trong ứng dụng thực tế sẽ có những sự kiện không nhất thiết phải gắn trực tiếp với Model.
Ví dụ:
User đăng ký tài khoản → gửi email chào mừng.
Đơn hàng được đặt → gửi thông báo.
Bài viết được publish → ghi log.
Thanh toán thành công → cập nhật dữ liệu.
User đăng ký → tạo một số dữ liệu liên quan.
Post được publish → thông báo cho người quản trị.
Lúc này chúng ta có thể sử dụng:
Event & Listener
Mô hình:
Một hành động xảy ra
│
▼
Event
│
▼
Listener
│
├── Gửi email
├── Ghi log
├── Gửi notification
└── Xử lý dữ liệu📑 MỤC LỤC
🏗️ Tạo Event
1. 🎯 Event & Listener là gì?
Event có thể hiểu đơn giản là:
Một thông báo cho biết một điều gì đó đã xảy ra trong ứng dụng.
Ví dụ:
UserRegistered
PostPublished
OrderCreated
PaymentCompleted
Event không nhất thiết phải trực tiếp xử lý công việc.
Nó chỉ mang thông tin:
"User vừa đăng ký"
Sau đó Listener sẽ nhận Event và thực hiện công việc.
Ví dụ:
User đăng ký
│
▼
UserRegistered
│
▼
SendWelcomeEmail
Ở đây:
UserRegistered
là Event.
Còn:
SendWelcomeEmail
là Listener.
2. 🧩 Vì sao cần Event & Listener?
Hãy tưởng tượng Controller có:
public function register(Request $request)
{
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($request->password),
]);
// Gửi email
// Ghi log
// Gửi notification
// Tạo dữ liệu khác
// Xử lý thêm...
}
Ban đầu nhìn không có vấn đề gì.
Nhưng ứng dụng càng lớn, Controller sẽ càng dài.
Ví dụ:
RegisterController
│
├── Create User
├── Send Email
├── Write Log
├── Create Profile
├── Send Notification
└── ...
Chúng ta có thể tách ra:
RegisterController
│
▼
UserRegistered Event
│
├── SendWelcomeEmail
├── CreateUserProfile
└── LogUserRegistration
Controller chỉ cần phát ra Event.
3. ⚙️ Event khác Observer như thế nào?
Đây là điểm rất quan trọng.
Observer thường gắn với:
Eloquent Model
Ví dụ:
Post
│
└── PostObserver
Observer quan tâm đến:
created
updated
deleted
restored
Trong khi Event có thể đại diện cho một nghiệp vụ của toàn bộ ứng dụng.
Ví dụ:
UserRegistered
PostPublished
OrderPaid
PaymentCompleted
Có thể hình dung:
Observer
Post
│
└── updated
│
▼
PostObserver
Event
PostController
│
└── PostPublished
│
▼
Listener
Observer:
"Model Post vừa xảy ra chuyện gì?"
Event:
"Trong ứng dụng vừa xảy ra nghiệp vụ gì?"
4. 🏗️ Tạo Event
Laravel cung cấp Artisan command:
php artisan make:event UserRegistered
📋 Copy
Laravel sẽ tạo:
app/
└── Events/
└── UserRegistered.php
📋 Copy
Một Event cơ bản:
<?php
namespace App\Events;
class UserRegistered
{
//
}
📋 Copy
Đây là một Event.
Nhưng hiện tại Event chưa chứa thông tin gì.
Chúng ta sẽ truyền dữ liệu vào Event ở phần tiếp theo.
5. 📦 Truyền dữ liệu vào Event
Thông thường Event cần mang theo dữ liệu.
Ví dụ:
$user = User::find(1);
Chúng ta muốn Event biết User nào vừa đăng ký.
Event:
<?php
namespace App\Events;
use App\Models\User;
class UserRegistered
{
public function __construct(
public User $user
) {
}
}
📋 Copy
Bây giờ Event chứa:
UserRegistered
│
└── user
Khi tạo Event:
event(new UserRegistered($user));
📋 Copy
Listener có thể lấy:
$event->user
6. 📣 Phát Event
Sau khi có Event, chúng ta cần phát nó.
Laravel cung cấp helper:
event(new UserRegistered($user));
📋 Copy
Ví dụ:
public function register(Request $request)
{
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($request->password),
]);
event(new UserRegistered($user));
return redirect()->route('login');
}
📋 Copy
Luồng:
User đăng ký
│
▼
User::create()
│
▼
UserRegistered
│
▼
Listeners
Event được phát ra sau khi User được tạo.
7. 👂 Listener là gì?
Nếu Event là:
"User đã đăng ký"
thì Listener là thành phần:
"Vậy tôi sẽ làm gì khi User đăng ký?"
Ví dụ:
UserRegistered
│
▼
SendWelcomeEmail
Listener nhận Event và xử lý.
Tạo Listener:
php artisan make:listener SendWelcomeEmail --event=UserRegistered
📋 Copy
Laravel tạo:
app/
└── Listeners/
└── SendWelcomeEmail.php
📋 Copy
8. 🏗️ Cấu trúc Listener
Listener cơ bản:
<?php
namespace App\Listeners;
use App\Events\UserRegistered;
class SendWelcomeEmail
{
public function handle(UserRegistered $event): void
{
//
}
}
📋 Copy
Phương thức quan trọng nhất là:
handle()
Nó nhận Event:
public function handle(UserRegistered $event): void
{
//
}
📋 Copy
Sau đó có thể lấy User:
$event->user
Ví dụ:
public function handle(UserRegistered $event): void
{
$user = $event->user;
logger("User {$user->id} vừa đăng ký");
}
📋 Copy
9. 🔗 Event kết nối với Listener
Bây giờ chúng ta có:
UserRegistered
và:
SendWelcomeEmail
Quan hệ:
UserRegistered
│
▼
SendWelcomeEmail
Khi:
event(new UserRegistered($user));
📋 Copy
Laravel sẽ tìm các Listener đang lắng nghe Event này.
Sau đó gọi:
handle()
Luồng hoàn chỉnh:
Controller
│
▼
event(new UserRegistered($user))
│
▼
UserRegistered
│
▼
SendWelcomeEmail
│
▼
handle(UserRegistered $event)
10. 📝 Đăng ký Event và Listener
Laravel cần biết:
Event nào
↓
Listener nào
Trong Laravel hiện đại, việc khai báo có thể được thực hiện thông qua Event discovery hoặc cấu hình Event/Listener tùy cấu trúc ứng dụng.
Với project học tập, điều quan trọng trước tiên là hiểu mối quan hệ:
Event
│
├── Listener A
├── Listener B
└── Listener C
Một Event hoàn toàn có thể có nhiều Listener.
Ví dụ:
UserRegistered
│
├── SendWelcomeEmail
├── CreateUserProfile
└── LogRegistration
Một sự kiện có thể kích hoạt nhiều công việc độc lập.
11. 🔥 Một Event có thể có nhiều Listener
Đây là một trong những ưu điểm lớn của Event.
Ví dụ:
PostPublished
│
├── SendNotification
├── WriteActivityLog
├── UpdateStatistics
└── NotifySubscribers
Controller chỉ cần:
event(new PostPublished($post));
📋 Copy
Không cần:
sendNotification();
writeActivityLog();
updateStatistics();
notifySubscribers();
📋 Copy
Controller chỉ phát ra:
PostPublished
Các Listener tự xử lý phần việc của mình.
12. 📰 Ví dụ thực tế với Blog CMS
Trong Blog CMS của chúng ta, giả sử khi Post được publish:
Post Published
│
▼
PostPublished
Chúng ta muốn:
PostPublished
│
├── Ghi log
├── Gửi notification
└── Cập nhật thống kê
Tạo Event:
php artisan make:event PostPublished
📋 Copy
Event:
<?php
namespace App\Events;
use App\Models\Post;
class PostPublished
{
public function __construct(
public Post $post
) {
}
}
📋 Copy
13. 📣 Phát Event khi Post được publish
Trong Controller:
$post->update([
'status' => 'published',
]);
Sau đó:
event(new PostPublished($post));
📋 Copy
Ví dụ:
public function publish(Post $post)
{
$post->update([
'status' => 'published',
]);
event(new PostPublished($post));
return redirect()
->route('posts.index');
}
📋 Copy
Luồng:
Publish Post
│
▼
PostController
│
▼
Post::update()
│
▼
PostPublished
│
├── Listener
├── Listener
└── Listener
14. 🧾 Listener ghi Log
Tạo:
php artisan make:listener LogPublishedPost --event=PostPublished
📋 Copy
Listener:
<?php
namespace App\Listeners;
use App\Events\PostPublished;
class LogPublishedPost
{
public function handle(PostPublished $event): void
{
logger(
"Post {$event->post->id} đã được publish"
);
}
}
📋 Copy
Khi Event:
event(new PostPublished($post));
📋 Copy
Listener sẽ nhận:
$event->post
và ghi Log.
15. 🔔 Listener gửi Notification
Chúng ta có thể tạo Listener khác:
php artisan make:listener NotifyPostPublished --event=PostPublished
📋 Copy
Ví dụ:
<?php
namespace App\Listeners;
use App\Events\PostPublished;
class NotifyPostPublished
{
public function handle(PostPublished $event): void
{
$post = $event->post;
// Gửi notification
}
}
📋 Copy
Bây giờ:
PostPublished
│
├── LogPublishedPost
│
└── NotifyPostPublished
Một Event → nhiều Listener.
16. ⚖️ Event & Listener khác Service như thế nào?
Đây là một điểm người mới học Laravel rất dễ nhầm.
Service thường được gọi khi chúng ta chủ động muốn thực hiện một nghiệp vụ.
Ví dụ:
$postService->publish($post);
📋 Copy
Còn Event:
event(new PostPublished($post));
📋 Copy
mang ý nghĩa:
"Post đã được publish."
Listener:
"Tôi nghe sự kiện đó và thực hiện công việc của tôi."
Có thể hình dung:
Service
Controller
│
▼
Service
│
▼
Thực hiện nghiệp vụ
Event
Controller
│
▼
Event
│
▼
Listener
│
▼
Phản ứng với sự kiện
17. 🧠 Event không nhất thiết chỉ dành cho Model
Observer chủ yếu xoay quanh Eloquent Model Event.
Event thì rộng hơn.
Ví dụ:
UserRegistered
PostPublished
OrderPaid
PaymentFailed
PasswordChanged
ImportCompleted
ReportGenerated
Những sự kiện này có thể liên quan đến:
Model
Controller
Service
Job
Command
API
Event giúp mô tả những gì đang xảy ra trong ứng dụng.
.
18. 🚀 Event và Queue
Một Listener có thể thực hiện công việc nặng.
Ví dụ:
PostPublished
│
▼
GeneratePostImage
│
▼
Xử lý ảnh lớn
Nếu xử lý trực tiếp:
User
│
▼
Publish Post
│
▼
Listener
│
▼
Xử lý 20 giây
│
▼
Response
Người dùng phải chờ.
Trong trường hợp này, Listener có thể được đưa vào Queue.
Ví dụ Listener implement:
ShouldQueue
Khi đó:
User
│
▼
Publish Post
│
▼
Event
│
▼
Queued Listener
│
└──────► Queue
│
▼
Worker
│
▼
Xử lý nền
Đây là lý do Event & Listener thường xuất hiện trước phần Queue trong kiến trúc Laravel.
19. ⚠️ Không nên nhét mọi thứ vào Listener
Event & Listener giúp tách code.
Nhưng không có nghĩa:
Listener
↓
500 dòng code
là tốt.
Ví dụ:
class PostPublishedListener
{
public function handle(PostPublished $event): void
{
// 300 dòng xử lý...
}
}
Không nên.
Nếu công việc lớn, có thể tách:
Listener
│
├── Service
├── Job
└── Action
Ví dụ:
public function handle(PostPublished $event): void
{
GeneratePostStatistics::run($event->post);
}
Listener trở thành nơi kết nối thay vì chứa toàn bộ nghiệp vụ.
20. 🆚 Observer vs Event & Listener
Đây là bảng cần nhớ:
| Observer | Event & Listener |
|---|---|
| Gắn với Model | Gắn với nghiệp vụ/sự kiện ứng dụng |
| Theo dõi Eloquent Event | Phát ra Event tùy ý |
created | UserRegistered |
updated | PostPublished |
deleted | OrderPaid |
restored | PaymentCompleted |
| Phản ứng trực tiếp với Model | Có thể có nhiều Listener |
| Thường dùng cho Model lifecycle | Phù hợp business event |
Ví dụ:
Observer
Post
│
└── deleted
│
▼
PostObserver
Trong khi:
Event
PostPublished
│
├── LogPublishedPost
├── NotifyPostPublished
└── UpdateStatistics
Điểm quan trọng:
Observer theo dõi vòng đời Model.
Event mô tả một sự kiện/nghiệp vụ xảy ra trong ứng dụng.
21. 🧠 Tóm tắt bài học
Event & Listener là cơ chế giúp chúng ta tách:
"Sự kiện xảy ra"
khỏi:
"Công việc cần thực hiện khi sự kiện đó xảy ra."
Tạo Event:
php artisan make:event UserRegistered
📋 Copy
Tạo Listener:
php artisan make:listener SendWelcomeEmail --event=UserRegistered
📋 Copy
Event:
class UserRegistered
{
public function __construct(
public User $user
) {
}
}
📋 Copy
Phát Event:
event(new UserRegistered($user));
📋 Copy
Listener:
class SendWelcomeEmail
{
public function handle(UserRegistered $event): void
{
$user = $event->user;
// Xử lý công việc
}
}
📋 Copy
Mô hình cần nhớ:
Controller / Service
│
▼
Event
│
├──────────────┐
▼ ▼
Listener A Listener B
│ │
▼ ▼
Công việc Công việc
🎯 Ghi nhớ
Observer: Model xảy ra Event → Observer phản ứng.
Event: Một sự kiện nghiệp vụ xảy ra → phát thông báo.
Listener: Nghe Event → thực hiện công việc.
Ví dụ:
Post
│
└── updated
│
▼
PostObserver
là cách tiếp cận của Observer.
Còn:
PostPublished
│
├── LogPublishedPost
├── NotifyPostPublished
└── UpdateStatistics
là cách tiếp cận Event & Listener.
Và khi Listener cần xử lý công việc nặng:
Event
│
▼
Listener
│
▼
Queue
│
▼
Worker
Đây chính là cầu nối để chúng ta bước sang các nội dung tiếp theo về Queue, Mail và Notification trong Laravel.




Không có nhận xét nào:
Đăng nhận xét