NTM Solutions

Bài đăng nổi bật

🚀 Laravel 12 (2026) — Từ PHP Core đến Full Stack📘

Nếu cập nhật theo Laravel 12 LTS (2026) thì mình sẽ chia thành các phần như sau để người học đi từ PHP Core → Laravel → Triển khai dự án th...

Chủ Nhật, 13 tháng 9, 2026

📘 LARAVEL 13 — BÀI 37 — NOTIFICATION

Trong Bài 36 — Mail, chúng ta đã học cách Laravel gửi email bằng:

Mail
  ↓
Mailable
  ↓
Blade
  ↓
SMTP
  ↓
Người nhận

Nhưng trong một ứng dụng thực tế, thông báo không chỉ có Email.

Người dùng có thể cần nhận thông báo qua:

  • 📧 Email

  • 🗃️ Database

  • 📱 SMS

  • 💬 Slack

  • 🔔 Các kênh thông báo khác

Đây chính là lúc Notification của Laravel trở nên hữu ích.

Notification giúp chúng ta xây dựng một thông báo theo cách thống nhất, sau đó quyết định thông báo đó sẽ được gửi qua kênh nào.


📚 MỤC LỤC

Trong bài này chúng ta sẽ tìm hiểu:

1. Notification là gì?
2. Notification khác Mail thế nào?
3. Tạo Notification
4. notify()
5. Notifiable
6. Mail Notification
7. Database Notification
8. Đọc Notification
9. Đánh dấu đã đọc
10. Xóa Notification
11. Markdown Notification
12. Notification + Queue
13. Notification + Event
14. Notification theo nhiều kênh
15. Notification trong Blog CMS
16. Bài tập thực hành
17. Tổng kết

1. 🔔 Notification trong Laravel là gì?

Notification là cơ chế của Laravel dùng để gửi thông báo đến một đối tượng nhận thông báo.

Ví dụ:

User đăng ký
     ↓
Notification
     ↓
"Chào mừng bạn!"

Hoặc:

Admin xuất bản bài viết
     ↓
Notification
     ↓
"Có bài viết mới"

Hoặc:

Đơn hàng hoàn tất
     ↓
Notification
     ↓
"Đơn hàng #1001 đã được giao"

Notification đặc biệt hữu ích vì một thông báo có thể được gửi qua nhiều channel.

Ví dụ:

                    Notification
                         │
            ┌────────────┼────────────┐
            ▼            ▼            ▼
          Email       Database      Slack

2. 📧 Notification khác Mail thế nào?

Đây là điểm rất dễ nhầm.

Mail

Mail tập trung vào việc tạo và gửi email.

Mailable
    ↓
Email

Ví dụ:

Mail::to($user->email)
    ->send(new WelcomeUser($user));

Notification

Notification tập trung vào thông báo.

Notification
      ↓
   Channel
      ↓
Email / Database / Slack / ...

Ví dụ:

$user->notify(
    new NewPostNotification($post)
);

Notification có thể chọn nhiều channel:

return ['mail', 'database'];

Vì vậy có thể hiểu đơn giản:

Mailable = xây dựng một email.

Notification = xây dựng một thông báo có thể đi qua nhiều kênh.


3. 👤 Notification cần đối tượng nhận

Notification thường được gửi tới một đối tượng có trait:

Notifiable

Thông thường chúng ta sẽ thấy trait này trong model User.

Ví dụ:

use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;
}

Sau đó User có thể nhận Notification:

$user->notify(
    new NewPostNotification($post)
);

Luồng:

User
 │
 └── Notifiable
          │
          ▼
    Notification

4. 🛠️ Tạo Notification

Laravel cung cấp Artisan để tạo Notification:

php artisan make:notification NewPostNotification

Laravel tạo:

app/
└── Notifications/
    └── NewPostNotification.php

Một Notification thường có cấu trúc:

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;

class NewPostNotification extends Notification
{
    use Queueable;

    public function __construct()
    {
        //
    }

    public function via(object $notifiable): array
    {
        return ['mail'];
    }
}

Phần quan trọng nhất là:

via()

Nó quyết định Notification được gửi qua channel nào.


5. 📡 via() — chọn Channel

Ví dụ chỉ gửi Email:

public function via(object $notifiable): array
{
    return ['mail'];
}

Gửi Database:

public function via(object $notifiable): array
{
    return ['database'];
}

Gửi cả hai:

public function via(object $notifiable): array
{
    return [
        'mail',
        'database',
    ];
}

Mô hình:

             Notification
                   │
             ┌─────┴─────┐
             ▼           ▼
           Mail       Database

Đây là một trong những ưu điểm lớn của Notification.

Laravel lưu trong bảng notifications. Bạn cần chạy migration:

php artisan notifications:table
php artisan migrate

Chỉnh trong class NewPostNotification

use App\Models\Post;

class NewPostNotification extends Notification
{
    use Queueable;

    public $post;

    /**
     * Create a new notification instance.
     */
    public function __construct(Post $post)
    {
        $this->post = $post;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @return array
     */
    public function via(object $notifiable): array
    {
        return [
            'mail',
            'database',
        ];
    }

    /**
     * Get the mail representation of the notification.
     */
    public function toMail(object $notifiable): MailMessage
    {
        return (new MailMessage)
        ->subject('Có bài viết mới')
        ->greeting('Xin chào!')
        ->line('Một bài viết mới vừa được tạo: ' . $this->post->title)
        ->action(
            'Xem bài viết',
            route('blog.show', $this->post->slug)
        )
        ->line('Cảm ơn bạn đã theo dõi!');
    }


    public function toDatabase($notifiable)
    {
        return [
            'post_id' => $this->post->id,
            'title' => $this->post->title,
            'slug' => $this->post->slug,
        ];
    }
    ...
}

Sau mục 7, kiểm tra trong DB xem có bản ghi mới chưa().


6. 📧 Mail Notification

Ví dụ chúng ta muốn thông báo:

Có bài viết mới được xuất bản.

Notification:

public function via(object $notifiable): array
{
    return ['mail'];
}

Sau đó tạo:

public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
        ->subject('Có bài viết mới')
        ->greeting('Xin chào!')
        ->line('Một bài viết mới vừa được xuất bản.')
        ->action(
            'Xem bài viết',
            url('/blog')
        )
        ->line('Cảm ơn bạn đã theo dõi!');
}

Import:

use Illuminate\Notifications\Messages\MailMessage;

Laravel sẽ xây dựng email từ Notification.

Ghi chú: nếu có lỗi chỗ này, Laravel 13 sẽ gửi mẫu mail default của họ.


7. 🚀 Gửi Notification

Sau khi có Notification vào PostController

use App\Models\User;
use Illuminate\Support\Facades\Auth;

public function store(Request $request)
{
    $post = Post::create([
        ...
    ]);

    $post->tags()->sync($request->tags ?? []);

    if ($post->status === 'published') {
        event(new PostPublished($post));
    }

    // Lấy user hiện tại từ Auth sau khi login
    $user = Auth::user();
    $user->notify(new NewPostNotification($post));

    return redirect()
        ->route('admin.posts.show', $post)
        ->with('success', 'Bài viết đã được tạo thành công.');
}

Hoặc:

$user->notify(
    new NewPostNotification($post)
);

Laravel sẽ gọi:

$user
   ↓
notify()
   ↓
Notification
   ↓
via()
   ↓
mail
   ↓
Email

8. 🗃️ Database Notification

Một tính năng rất hay của Laravel Notification là lưu thông báo vào Database.

Ví dụ:

🔔 Thông báo

Có bài viết mới.

5 phút trước

Notification:

public function via(object $notifiable): array
{
    return [
        'database',
    ];
}

Sau đó định nghĩa:

public function toDatabase(
    object $notifiable
): array {
    return [
        'title' => 'Có bài viết mới',
        'message' => 'Một bài viết vừa được xuất bản.',
    ];
}

Laravel sẽ lưu dữ liệu Notification vào database.


9. 🗄️ Tạo bảng Notifications

Laravel cung cấp Artisan command:

php artisan make:notifications-table

Sau đó:

php artisan migrate

Laravel tạo bảng:

notifications

Bảng này dùng để lưu các Database Notifications.

Một Notification có thể được liên kết với User thông qua hệ thống polymorphic của Laravel.

Mô hình:

users
  │
  │
  ▼
notifications

10. 🔔 Lấy Notification của User

User có thể truy cập các Notification của mình:

$user->notifications

Ví dụ:

foreach ($user->notifications as $notification) {

    echo $notification->data['title'];

}

Dữ liệu trong data chính là dữ liệu mà chúng ta trả về từ:

toDatabase()

Ví dụ:

return [
    'title' => 'Có bài viết mới',
    'message' => 'Laravel 13 đã ra mắt.',
];

11. 🆕 Unread Notifications

Laravel cũng hỗ trợ phân biệt:

Unread
Read

Có thể lấy Notification chưa đọc:

$user->unreadNotifications

Ví dụ:

$count = $user
    ->unreadNotifications
    ->count();

Sau đó hiển thị trên Navbar:

🔔 5

12. 👀 Đánh dấu Notification đã đọc

Khi người dùng mở Notification:

$notification->markAsRead();

Ví dụ:

foreach ($user->unreadNotifications as $notification) {

    $notification->markAsRead();

}

Có thể đánh dấu tất cả:

$user->unreadNotifications
    ->markAsRead();

Mô hình:

NEW
 │
 ▼
Unread
 │
 │ User mở
 ▼
Read

13. 🗑️ Xóa Notification

Notification không nhất thiết phải tồn tại mãi mãi.

Có thể xóa:

$notification->delete();

Hoặc:

$user->notifications()->delete();

Ví dụ trong trang:

🔔 Notifications

Có bài viết mới
Đơn hàng đã giao
Tài khoản đã được cập nhật

[ Xóa tất cả ]

14. 📝 Markdown Notification

Laravel cũng hỗ trợ Notification sử dụng Markdown.

Ví dụ:

return (new MailMessage)
    ->subject('Bài viết mới')
    ->greeting('Xin chào!')
    ->line('Một bài viết mới vừa được xuất bản.')
    ->action(
        'Xem bài viết',
        url('/blog')
    )
    ->line('Cảm ơn bạn!');

Laravel sẽ tạo email dựa trên các thành phần Markdown Mail Notification.

Điều này giúp chúng ta không phải tự xây dựng toàn bộ HTML email.


15. 🔀 Một Notification — nhiều Channel

Đây mới là sức mạnh thực sự.

Ví dụ:

public function via(object $notifiable): array
{
    return [
        'mail',
        'database',
    ];
}

Khi:

$user->notify(
    new NewPostNotification($post)
);

Laravel thực hiện:

                  NewPostNotification
                           │
                           ▼
                         via()
                           │
                  ┌────────┴────────┐
                  ▼                 ▼
                Mail             Database
                  │                 │
                  ▼                 ▼
               Email          Notification

Người dùng vừa nhận email:

📧 Có bài viết mới

vừa có Notification trong website:

🔔 Có bài viết mới

16. ⚡ Notification + Queue

Đây là phần rất quan trọng vì chúng ta vừa học Queue ở Bài 35.

Nếu Notification gửi Email:

User Action
    ↓
Notification
    ↓
Email
    ↓
SMTP

Request có thể phải chờ.

Thay vào đó, Notification có thể được đưa vào Queue.

Một Notification có thể implement:

ShouldQueue

Ví dụ:

use Illuminate\Contracts\Queue\ShouldQueue;

class NewPostNotification
    extends Notification
    implements ShouldQueue
{
    use Queueable;
}

Khi đó:

User
 ↓
Notification
 ↓
Queue
 ↓
Response ngay
 ↓
Queue Worker
 ↓
Email / Database / ...

Đây là mô hình rất phù hợp với hệ thống production.


17. 🔄 Event + Listener + Notification

Chúng ta đã học:

Bài 33
Observer

Bài 34
Event & Listener

Bài 35
Queue

Bài 36
Mail

Bây giờ Bài 37 kết nối tất cả:

                 User Action
                     │
                     ▼
                   Event
                     │
                     ▼
                  Listener
                     │
                     ▼
               Notification
                     │
              ┌──────┴──────┐
              ▼             ▼
            Email        Database
              │
              ▼
            Queue

Ví dụ:

Admin publish Post
        ↓
PostPublished
        ↓
SendNewPostNotification
        ↓
NewPostNotification
        ↓
Queue
        ↓
Subscribers

Đây là kiến trúc rất đẹp cho Blog CMS.


18. 📰 Notification trong Blog CMS

Hãy áp dụng vào dự án Blog CMS chúng ta đang xây dựng.

Giả sử có:

User
Post
Category

Một User có thể đăng ký nhận thông báo.

Khi Admin xuất bản Post:

Admin
  │
  ▼
Publish Post
  │
  ▼
Event
  │
  ▼
Listener
  │
  ▼
Notification
  │
  ├───────────────┐
  ▼               ▼
Email          Database

Database Notification:

🔔 Thông báo

Bài viết mới:
Laravel 13 — Notification

[Xem bài viết]

19. 📊 Notification Badge

01 ứng dụng thực tế thường hiển thị số Notification chưa đọc trong navigation.blade.php sau tên user.

Ví dụ Blade:

<x-slot name="trigger">
    <button class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 bg-white hover:text-gray-700 focus:outline-none transition ease-in-out duration-150">
        <div>{{ Auth::user()->name }}</div>                            

        <!-- Phần Notifications -->
        <div class="hidden sm:flex sm:items-center sm:ms-6" 
            x-data="{ count: {{ Auth::user()->unreadNotifications->count() }} }"
            x-init="
                window.addEventListener('notification-read', e => {
                    if(count > 0) count--;
                });
                window.addEventListener('notification-read-all', e => {
                    count = 0;
                });
            ">
            <a href="{{ route('notifications.index') }}" class="relative inline-flex items-center px-3 py-2 text-gray-500 hover:text-gray-700">
                <!-- Icon chuông -->
                <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                        d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 
                            6.002 0 00-4-5.659V4a2 2 0 10-4 0v1.341C7.67 
                            6.165 6 8.388 6 11v3.159c0 .538-.214 
                            1.055-.595 1.436L4 17h5m6 0v1a3 3 0 
                            11-6 0v-1m6 0H9" />
                </svg>

                <!-- Badge số lượng -->
                <template x-if="count > 0">
                    <span class="absolute top-0 right-0 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-white bg-red-600 rounded-full"
                        x-text="count"></span>
                </template>
            </a>
        </div>
        <!-- END Phần Notifications -->
        

Kết quả:

┌───────────────┐
│ 🔔 3          │
└───────────────┘

Người dùng click:

🔔
 ↓
Notifications
 ↓
Mark as Read

20. 📋 Trang Notification

1. Tạo route trong routes/web.php

// bài 37 - Notifications
use App\Http\Controllers\NotificationController;
Route::prefix('notifications')->name('notifications.')->middleware('auth')->group(function () {
    // 1. Khai báo các route TĨNH trước
    Route::get('/', [NotificationController::class, 'index'])->name('index');
    Route::post('/read-all', [NotificationController::class, 'markAllAsRead'])->name('readAll');
    Route::delete('/delete-all', [NotificationController::class, 'deleteAll'])->name('deleteAll');

    // 2. Khai báo các route CÓ THAM SỐ {id} sau
    Route::post('/{id}/read', [NotificationController::class, 'markAsRead'])->name('read');
    Route::delete('/{id}', [NotificationController::class, 'destroy'])->name('destroy');
});

2. Tạo controller

php artisan make:controller NotificationController

Trong file app/Http/Controllers/NotificationController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class NotificationController extends Controller
{
    public function index()
    {
        $notifications = auth()->user()->notifications;
        return view('notifications.index', compact('notifications'));
    }

    public function markAsRead($id)
    {
        $notification = auth()->user()->notifications()->find($id);

        if ($notification) {
            $notification->markAsRead();
        }

        return redirect()->route('notifications.index');
    }

    public function markAllAsRead()
    {
        // Đánh dấu tất cả thông báo chưa đọc của user hiện tại thành đã đọc
        auth()->user()->unreadNotifications->markAsRead();

        return response()->json(['success' => true]);
    }

    public function deleteAll()
    {
        // Xóa toàn bộ thông báo (cả đã đọc lẫn chưa đọc) của user hiện tại
        auth()->user()->notifications()->delete();

        return response()->json(['success' => true]);
    }

    public function destroy($id)
    {
        $notification = auth()->user()->notifications()->findOrFail($id);
        $notification->delete();

        return response()->json(['success' => true]);
    }

}

3. Tạo view resources/views/notifications/index.blade.php

<x-app-layout>
    <div class="max-w-7xl mx-auto py-8" 
         x-data="{ 
            unreadCount: {{ auth()->user()->unreadNotifications->count() }},
            allRead: false,
            allDeleted: false
         }">

        <x-ui.card>
            <!-- THANH TIÊU ĐỀ & CÁC NÚT THAO TÁC HÀNG LOẠT -->
            <div class="flex items-center justify-between mb-4 border-b pb-3">
                <h1 class="text-2xl font-bold flex items-center">
                    Thông báo
                    <template x-if="unreadCount > 0">
                        <span class="ml-2 inline-flex items-center px-2 py-1 text-xs font-bold leading-none text-white bg-red-600 rounded-full"
                              x-text="unreadCount"></span>
                    </template>
                </h1>

                <div class="flex items-center space-x-4">
                    <!-- Nút Đánh dấu tất cả đã đọc -->
                    <button 
                        x-show="unreadCount > 0"
                        @click.prevent="
                            fetch('{{ route('notifications.readAll') }}', {
                                method: 'POST',
                                headers: {
                                    'X-CSRF-TOKEN': '{{ csrf_token() }}',
                                    'Accept': 'application/json'
                                }
                            }).then(res => res.json())
                              .then(data => {
                                  if(data.success){
                                      unreadCount = 0;
                                      allRead = true;
                                  }
                              })
                        "
                        class="text-sm text-blue-600 hover:text-blue-800 font-medium hover:underline">
                        Đánh dấu tất cả là đã đọc
                    </button>

                    <!-- Nút Xóa tất cả thông báo -->
                    <button 
                        @click.prevent="
                            if (confirm('Bạn có chắc chắn muốn xóa TẤT CẢ thông báo?')) {
                                fetch('{{ route('notifications.deleteAll') }}', {
                                    method: 'DELETE',
                                    headers: {
                                        'X-CSRF-TOKEN': '{{ csrf_token() }}',
                                        'Accept': 'application/json'
                                    }
                                }).then(res => res.json())
                                  .then(data => {
                                      if(data.success){
                                          unreadCount = 0;
                                          allDeleted = true;
                                      }
                                  })
                            }
                        "
                        class="text-sm text-red-600 hover:text-red-800 font-medium hover:underline">
                        Xóa tất cả
                    </button>
                </div>
            </div>

            <!-- DANH SÁCH THÔNG BÁO -->
            <template x-if="!allDeleted">
                <div>
                    @forelse($notifications as $notification)
                        <div class="border-b py-3 flex items-center justify-between" 
                             x-data="{ 
                                read: {{ $notification->read_at ? 'true' : 'false' }}, 
                                deleted: false 
                             }"
                             x-show="!deleted"
                             x-transition>

                            <div>
                                <strong>{{ $notification->data['title'] }}</strong>
                                <p class="text-gray-600 text-sm">{{ $notification->data['slug'] }}</p>
                            </div>

                            <div class="flex items-center space-x-3">
                                <!-- Trạng thái Đã đọc / Chưa đọc lẻ -->
                                <template x-if="!read && !allRead">
                                    <button 
                                        @click.prevent="
                                            fetch('{{ route('notifications.read', $notification->id) }}', {
                                                method: 'POST',
                                                headers: {
                                                    'X-CSRF-TOKEN': '{{ csrf_token() }}',
                                                    'Accept': 'application/json'
                                                }
                                            }).then(res => res.json())
                                              .then(data => {
                                                  if(data.success){
                                                      read = true;
                                                      if(unreadCount > 0) unreadCount--;
                                                  }
                                              })
                                        "
                                        class="text-blue-600 hover:underline text-sm">
                                        Đánh dấu đã đọc
                                    </button>
                                </template>

                                <template x-if="read || allRead">
                                    <span class="text-gray-400 text-sm">Đã đọc</span>
                                </template>

                                <!-- Nút Xóa từng thông báo -->
                                <button 
                                    @click.prevent="
                                        if (confirm('Bạn có chắc muốn xóa thông báo này?')) {
                                            fetch('{{ route('notifications.destroy', $notification->id) }}', {
                                                method: 'DELETE',
                                                headers: {
                                                    'X-CSRF-TOKEN': '{{ csrf_token() }}',
                                                    'Accept': 'application/json'
                                                }
                                            }).then(res => res.json())
                                              .then(data => {
                                                  if(data.success){
                                                      if(!read && !allRead && unreadCount > 0) {
                                                          unreadCount--;
                                                      }
                                                      deleted = true;
                                                  }
                                              })
                                        }
                                    "
                                    class="text-red-600 hover:underline text-sm">
                                    Xóa
                                </button>
                            </div>

                        </div>
                    @empty
                        <p class="text-gray-500 py-4">Không có thông báo nào.</p>
                    @endforelse
                </div>
            </template>

            <!-- THÔNG BÁO KHI ĐÃ XÓA SẠCH SẼ -->
            <template x-if="allDeleted">
                <p class="text-gray-500 py-4">Không có thông báo nào.</p>
            </template>
        </x-ui.card>
    </div>
</x-app-layout>


21. 🧱 Notification nên chứa gì?

Không nên nhồi quá nhiều dữ liệu vào Notification.

Ví dụ tốt:

return [
    'title' => 'Bài viết mới',
    'message' => 'Laravel 13 — Notification',
    'post_id' => $post->id,
];

Sau đó có thể dùng:

$post = Post::find(
    $notification->data['post_id']
);

Hoặc tốt hơn, xây dựng URL từ ID:

url('/posts/' . $notification->data['post_id'])

Mục tiêu là Notification chỉ chứa những thông tin cần thiết.


22. 🧠 Notification không thay thế Event

Hai khái niệm này khác nhau.

Event

Mô tả:

Một chuyện gì đó đã xảy ra.

Ví dụ:

PostPublished

Notification

Mô tả:

Thông báo cho ai đó về chuyện đó.

Ví dụ:

NewPostNotification

Có thể hình dung:

EVENT
"Post đã được publish"
       │
       ▼
LISTENER
"Thông báo cho subscribers"
       │
       ▼
NOTIFICATION
"Có bài viết mới"

23. 📧 Notification hay Mailable?

Có thể dùng quy tắc đơn giản:

Dùng Mailable khi:

Email phức tạp
Hóa đơn
Báo giá
PDF
Email marketing
Email template riêng

Dùng Notification khi:

Thông báo hệ thống
Thông báo bài viết
Thông báo đơn hàng
Thông báo tài khoản
Unread notification
Nhiều channel

Ví dụ:

Invoice
   ↓
Mailable

Trong khi:

"Đơn hàng của bạn đã được giao"
   ↓
Notification
   ├── Email
   └── Database

24. 🧪 Test Notification

Khi viết Test, chúng ta không muốn gửi Notification thật.

Laravel cung cấp:

Notification::fake();

Sau đó:

$user->notify(
    new NewPostNotification($post)
);

Kiểm tra:

Notification::assertSentTo(
    $user,
    NewPostNotification::class
);

Mô hình:

Test
 ↓
Notification::fake()
 ↓
Action
 ↓
Notification
 ↓
Assert

Không có email thật được gửi đi.


25. 🎯 Bài tập thực hành

Bây giờ hãy xây dựng Notification cho Blog CMS.

Bước 1 — Tạo Notification

php artisan make:notification NewPostNotification

Bước 2 — Notification nhận Post

public function __construct(
    public Post $post
) {}

Bước 3 — Chọn channel

public function via(object $notifiable): array
{
    return [
        'mail',
        'database',
    ];
}

Bước 4 — Mail

public function toMail(
    object $notifiable
): MailMessage {

    return (new MailMessage)
        ->subject('Có bài viết mới')
        ->greeting('Xin chào!')
        ->line(
            'Một bài viết mới vừa được xuất bản.'
        )
        ->action(
            'Xem bài viết',
            url('/posts/' . $this->post->id)
        );
}

Bước 5 — Database

public function toDatabase(
    object $notifiable
): array {

    return [
        'title' => 'Có bài viết mới',
        'message' => $this->post->title,
        'post_id' => $this->post->id,
    ];
}

Bước 6 — Gửi Notification

$user->notify(
    new NewPostNotification($post)
);

Bước 7 — Queue

Sau khi Notification hoạt động ổn định, chuyển sang:

implements ShouldQueue

Sau đó chạy:

php artisan queue:work

Khi đó hệ thống sẽ có:

Publish Post
     ↓
Notification
     ↓
Queue
     ↓
Worker
     ├── Email
     └── Database

26. 🏆 Kiến trúc Blog CMS sau Bài 37

Sau 37 bài, dự án của chúng ta bắt đầu có kiến trúc khá hoàn chỉnh:

                         BLOG CMS
                             │
              ┌──────────────┼──────────────┐
              │              │              │
              ▼              ▼              ▼
           Request         Event          Model
              │              │              │
              ▼              ▼              ▼
         Controller       Listener       Eloquent
              │              │
              │              ▼
              │         Notification
              │              │
              │       ┌──────┴──────┐
              │       ▼             ▼
              │     Mail         Database
              │       │
              │       ▼
              │     Queue
              │       │
              └───────┴──────────────► User

Đây không còn đơn thuần là:

Route
 ↓
Controller
 ↓
View

mà đã bắt đầu trở thành một ứng dụng có kiến trúc thực tế.


27. 📌 Những kiến thức cần nhớ

Thành phầnVai trò
NotificationĐại diện cho một thông báo
NotifiableCho phép đối tượng nhận Notification
notify()Gửi Notification
via()Chọn channel
toMail()Nội dung Mail Notification
toDatabase()Dữ liệu Database Notification
notificationsCác Notification của User
unreadNotificationsNotification chưa đọc
markAsRead()Đánh dấu đã đọc
ShouldQueueĐưa Notification vào Queue
Notification::fake()Fake Notification khi Test

28. 🔥 Tổng kết Bài 37

Notification giải quyết một bài toán rất phổ biến:

Làm thế nào để thông báo cho người dùng mà không phải tự xây dựng một hệ thống riêng cho từng loại thông báo?

Laravel cho phép chúng ta xây dựng:

                    🔔 Notification
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
           📧 Mail      🗃️ Database   💬 Channel khác
              │            │
              ▼            ▼
           Email       Notification
                           │
                           ▼
                         User

Và khi kết hợp với Queue:

Event
  ↓
Listener
  ↓
Notification
  ↓
Queue
  ↓
Worker
  ↓
Mail / Database

Đây là một trong những mô hình rất đáng học vì nó kết nối trực tiếp những kiến thức chúng ta đã học từ Bài 33 → Bài 37:

33 — Observer
       ↓
34 — Event & Listener
       ↓
35 — Queue
       ↓
36 — Mail
       ↓
37 — Notification

📘 Bài tiếp theo — Bài 38: Cache

Chúng ta sẽ chuyển từ bài toán:

"Làm sao thông báo cho User?"

sang:

"Làm sao để Laravel không phải truy vấn Database liên tục?"

và bắt đầu tìm hiểu:

Cache
Redis
File Cache
Database Cache
remember()
forget()
flush()
Cache::put()
Cache::get()

Đây sẽ là bước đầu tiên để tối ưu hiệu năng Laravel 13.

x1
quay về MỤC LỤC

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

Đăng nhận xét

Facebook Youtube RSS