NTM Solutions

Chủ Nhật, 30 tháng 8, 2026

📘 Laravel 12 (2026) — BÀI 34 — EVENT & LISTENER TRONG LARAVEL

Ở 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

  1. 🎯 Event & Listener là gì?

  2. 🧩 Vì sao cần Event & Listener?

  3. ⚖️ Event khác Observer như thế nào?

  4. 🏗️ Tạo Event

  5. 📦 Truyền dữ liệu vào Event

  6. 📣 Phát Event

  7. 👂 Listener là gì?

  8. 🏗️ Cấu trúc Listener

  9. 🔗 Event kết nối với Listener

  10. 📝 Đăng ký Event và Listener

  11. 🔥 Một Event có thể có nhiều Listener

  12. 📰 Ví dụ thực tế với Blog CMS

  13. 📣 Phát Event khi Post được publish

  14. 🧾 Listener ghi Log

  15. 🔔 Listener gửi Notification

  16. ⚖️ Event & Listener khác Service như thế nào?

  17. 🧠 Event không nhất thiết chỉ dành cho Model

  18. 🚀 Event và Queue

  19. ⚠️ Không nên nhét mọi thứ vào Listener

  20. 🆚 Observer vs Event & Listener

  21. 🧠 Tóm tắt bài học


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

Event.

Còn:

SendWelcomeEmail

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ớ:

ObserverEvent & Listener
Gắn với ModelGắn với nghiệp vụ/sự kiện ứng dụng
Theo dõi Eloquent EventPhát ra Event tùy ý
createdUserRegistered
updatedPostPublished
deletedOrderPaid
restoredPaymentCompleted
Phản ứng trực tiếp với ModelCó thể có nhiều Listener
Thường dùng cho Model lifecyclePhù 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

Facebook Youtube RSS