告別義大利麵程式碼:Laravel 通知系統的優雅實戰指南
資深工程師 Eric 警告:別再將 Mail::send() 或 Curl 塞爆 Controller,製造難以維護的「義大利麵程式碼」!Laravel Notifications 系統是將發送邏輯(Email、Slack、站內信)從業務核心中完美解耦的神器。它提供強大的抽象層,讓你用單一通知定義應對多種發送管道。最關鍵的是,透過實作 ShouldQueue 介面,能讓你的應用程式實現非同步發送,提供「秒回」的流暢使用者體驗。立即掌握這個現代化的架構,讓你的服務優雅且專業地與使用者對話!
嗨,我是 Eric,浪花科技的資深工程師。今天我們來聊聊一個我在 Code Review 時常看到讓人血壓升高的問題:「通知發送」。
我常常看到新手(甚至是有經驗的開發者)在 Controller 裡面直接寫 Mail::send(),然後隔了兩行又寫個 Curl 去打 Slack Webhook,最後還在同一個 function 裡面塞一段 SQL 把通知寫進資料庫。這種寫法就是典型的「義大利麵程式碼」。如果今天要改 Email 樣板怎麼辦?如果 Slack 掛了會不會卡住整個 Request?如果要新增 SMS 簡訊通知,你的 Controller 不就要爆炸了?
別再這樣折磨自己了。Laravel 早就為我們準備好了一個優雅的神器——Laravel 通知系統(Notifications)。它不僅是將發送邏輯抽象化,更是讓你的應用程式學會「說話」的關鍵架構。
為什麼你需要 Laravel Notifications?而不只是 Mail Facade
Laravel 的 Notification 系統是一個強大的抽象層。它的核心概念是:「一個通知,多種管道(Channels)」。
想像一下,當「訂單成立」時,你可能需要做三件事:
- 寄一封精美的 HTML Email 給客戶。
- 傳送一則 LINE 或 Slack 訊息給業務團隊。
- 在網站右上角的小鈴鐺(Database)儲存一條未讀通知。
如果你手刻這些邏輯,你的程式碼會充滿了各種第三方 API 的呼叫細節。但使用 Notifications,你只需要定義一個 OrderShipped 類別,Laravel 會自動幫你分發到指定的管道。這才叫做現代化的後端開發。
起手式:建立你的第一個通知
讓我們直接進入實戰。首先,用 Artisan 指令產生一個 Notification 類別。假設我們要處理的是「新會員註冊通知」。
php artisan make:notification NewUserRegistered
這會在 app/Notifications 目錄下產生一個檔案。打開它,你會看到幾個關鍵方法:via、toMail、toArray。
1. 決定發送管道 (via)
via 方法是交通指揮官,它決定這個通知要走哪條路。它可以動態判斷,例如:如果使用者設定不接收 Email,就只發站內信。
public function via($notifiable)
{
// 這裡可以回傳 ['mail', 'database', 'slack']
return ['mail', 'database'];
}
2. 定義 Email 內容 (toMail)
這是最常用的部分。Eric 建議盡量使用 Laravel 內建的 Line 函式,這樣產生的 Email 在 RWD 上效果非常好,不用自己去切 HTML table 搞死自己。
public function toMail($notifiable)
{
return (new MailMessage)
->subject('歡迎加入浪花科技!')
->greeting('你好,' . $notifiable->name)
->line('感謝您註冊我們的服務,我們非常高興能為您服務。')
->action('開始使用', url('/'))
->line('如果有任何問題,請隨時聯繫我們!');
}
進階應用:打造「站內信」系統 (Database Channel)
很多工程師問我:「Eric,網站右上角那個小鈴鐺通知要怎麼做?」
答案就在這裡。Laravel 內建了 database 驅動。首先,你需要準備一張表來存這些通知:
php artisan notifications:table
php artisan migrate
接著,在你的 Notification 類別中加入 toArray 或 toDatabase 方法:
public function toArray($notifiable)
{
return [
'order_id' => $this->order->id,
'amount' => $this->order->total,
'message' => '您的訂單 #' . $this->order->id . ' 已經成立',
'link' => '/orders/' . $this->order->id,
];
}
就這樣!當通知發送後,你的資料庫 notifications 表裡面就會多一筆 JSON 資料。在前端,你只需要這樣撈取:
// 取得該使用者的所有未讀通知
$user = Auth::user();
$notifications = $user->unreadNotifications;
// 標記為已讀
$user->unreadNotifications->markAsRead();
看吧,完全不需要自己手寫 CRUD,Laravel 都幫你包好了。
發送通知的兩種方式
要觸發通知,我們通常會使用 Notifiable Trait。在預設的 User Model 中,Laravel 已經幫你掛載好了。
方法一:透過 Model 發送
use App\Notifications\NewUserRegistered;
$user = User::find(1);
$user->notify(new NewUserRegistered($user));
方法二:使用 Notification Facade (適合批次發送)
如果你要發給一群人,用 Facade 效能會好一點(如果配合 Queue 的話)。
use Illuminate\Support\Facades\Notification;
$users = User::all();
Notification::send($users, new NewUserRegistered());
效能關鍵:千萬要使用 Queue (佇列)
這是 Eric 最想強調的一點。發送 Email 或打 Slack API 是非常耗時的 I/O 操作。如果你在使用者按下「註冊」按鈕的那一瞬間同步執行發送,使用者可能會看著瀏覽器轉圈圈轉個 3 到 5 秒。在現代 Web 體驗中,這是不及格的。
Laravel Notifications 整合 Queue 超級簡單。你只需要讓你的 Notification 類別實作 ShouldQueue 介面:
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class NewUserRegistered extends Notification implements ShouldQueue
{
use Queueable;
// ... 其他程式碼
}
只要加上 implements ShouldQueue,Laravel 就會自動把這個發送任務丟到背景執行(前提是你有設定好 Redis 或 Database Queue worker)。這樣使用者的介面就能達到「秒回」的流暢感。
串接 Slack 與 Discord
現在很多團隊協作都依賴 Slack 或 Discord。Laravel 官方支援 Slack,而 Discord 可以透過 Webhook 輕鬆串接。
以 Slack 為例,你需要安裝官方套件(Laravel 10+ 之後部分通知頻道被移出核心,需額外安裝),或者使用最原始的 Webhook 方式。如果是使用 Laravel 內建的 Slack 支援,你需要在 Notification 定義 toSlack:
public function toSlack($notifiable)
{
return (new SlackMessage)
->content('注意!有一筆大額訂單成立!');
}
如果是發送到特定的 Webhook(例如 On-Demand Notification),可以使用 route 方法:
Notification::route('slack', 'https://hooks.slack.com/services/...')
->notify(new OrderShipped($order));
Eric 的開發小囉嗦
技術是一回事,架構思維又是另一回事。在使用 Laravel Notifications 時,我有幾個建議:
- 不要把所有邏輯塞在
toMail:如果你發現 Email 邏輯太複雜,請考慮建立獨立的 Mailable 類別,然後在 Notification 裡回傳 Mailable 物件。 - 善用 Database Channel 做 Log:即使你不做站內信功能,將重要通知寫入資料庫也是很好的 Log 機制,方便日後除錯查帳。
- Markdown 是好朋友:Laravel 的 Email 支援 Markdown 語法,這比寫 HTML 乾淨多了,維護起來也比較像是在寫文件而不是寫程式。
總結
Laravel 通知系統(Notifications)是 Laravel 生態系中最優雅的設計之一。它將「業務邏輯」與「發送管道」解耦,讓你的程式碼具備極高的可讀性與擴充性。不管你是要寄信、傳簡訊,還是串接 Slack 機器人,Notifications 都是你的最佳選擇。
別再讓你的 App 當個啞巴,或是用義大利麵程式碼亂吼亂叫了。把通知系統架好,讓你的服務優雅地與使用者對話吧!
延伸閱讀
- Laravel 效能卡關?Redis 就是你的神兵利器!從快取到隊列,資深工程師帶你榨乾系統效能
- Laravel 通知系統玩膩了?資深工程師帶你手刻 Custom Channel,從簡訊到 LINE Notify 全搞定!
- Eloquent 是蜜糖還是毒藥?資深工程師的 Laravel ORM 實戰心法,避開效能地雷區
需要打造企業級的 Laravel 通知與自動化系統?
如果你的專案面臨訊息漏發、Queue 阻塞,或是需要串接複雜的第三方 API(如 LINE OA、WhatsApp),浪花科技的資深團隊能為你提供最穩固的架構方案。
常見問題 (FAQ)
Q1: toMail 和 Mailable 有什麼不同?什麼時候該用哪個?
toMail 適合簡單的文字通知,快速方便。但如果你需要高度客製化的 Email 版型、複雜的資料綁定,或是要在多個地方共用同一個 Email 樣板,建議建立獨立的 Mailable 類別,然後在 Notification 的 toMail 方法中回傳該 Mailable 物件。
Q2: 為什麼我的 Queue 通知沒有發送?
請檢查兩點:第一,你的 Notification 類別是否有 implements ShouldQueue。第二,你的伺服器上是否已經啟動了 Queue Worker (php artisan queue:work)。如果是本地開發,記得執行該指令;如果是正式環境,建議使用 Supervisor 來管理行程。
Q3: 資料庫通知表 (notifications table) 資料量太大會影響效能嗎?
會的。如果你頻繁使用 database channel,這張表會成長得非常快。建議定期寫排程 (Scheduler) 清理舊的已讀通知,例如使用 model prune 功能定期刪除一個月前的通知紀錄。






