跳到內容

通知

簡介

除了支援發送電子郵件之外,Laravel 還支援透過各種傳遞管道發送通知,包括電子郵件、簡訊(透過 Vonage,前身為 Nexmo)和 Slack。此外,還創建了各種社群構建的通知管道,以透過數十種不同的管道發送通知!通知也可以儲存在資料庫中,以便在您的 Web 介面中顯示。

通常,通知應該是簡短、資訊性的訊息,用於通知使用者您的應用程式中發生的某些事件。例如,如果您正在編寫帳單應用程式,您可能會透過電子郵件和 SMS 管道向使用者發送「發票已付款」通知。

產生通知

在 Laravel 中,每個通知都由一個單獨的類別表示,通常儲存在 app/Notifications 目錄中。如果您在應用程式中沒有看到此目錄,請別擔心 - 當您執行 make:notification Artisan 命令時,將會為您建立它。

1php artisan make:notification InvoicePaid

此命令將在您的 app/Notifications 目錄中放置一個新的通知類別。每個通知類別都包含一個 via 方法和可變數量的訊息建構方法,例如 toMailtoDatabase,這些方法將通知轉換為針對該特定管道量身定制的訊息。

發送通知

使用 Notifiable Trait

通知可以透過兩種方式發送:使用 Notifiable trait 的 notify 方法,或使用 Notification facadeNotifiable trait 預設包含在您應用程式的 App\Models\User 模型中。

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Foundation\Auth\User as Authenticatable;
6use Illuminate\Notifications\Notifiable;
7 
8class User extends Authenticatable
9{
10 use Notifiable;
11}

此 trait 提供的 notify 方法預期接收一個通知實例。

1use App\Notifications\InvoicePaid;
2 
3$user->notify(new InvoicePaid($invoice));

請記住,您可以在任何模型上使用 Notifiable trait。您不限於僅將其包含在您的 User 模型上。

使用 Notification Facade

或者,您可以透過 Notification facade 發送通知。當您需要向多個可通知的實體(例如使用者集合)發送通知時,此方法非常有用。若要使用 facade 發送通知,請將所有可通知的實體和通知實例傳遞給 send 方法。

1use Illuminate\Support\Facades\Notification;
2 
3Notification::send($users, new InvoicePaid($invoice));

您也可以使用 sendNow 方法立即發送通知。即使通知實作了 ShouldQueue 介面,此方法也會立即發送通知。

1Notification::sendNow($developers, new DeploymentCompleted($deployment));

指定傳遞管道

每個通知類別都有一個 via 方法,用於決定通知將透過哪些管道傳遞。通知可以透過 maildatabasebroadcastvonageslack 管道發送。

如果您想使用其他傳遞管道(例如 Telegram 或 Pusher),請查看社群驅動的 Laravel Notification Channels 網站

via 方法接收一個 $notifiable 實例,這將是接收通知的類別的實例。您可以使用 $notifiable 來決定應透過哪些管道傳遞通知。

1/**
2 * Get the notification's delivery channels.
3 *
4 * @return array<int, string>
5 */
6public function via(object $notifiable): array
7{
8 return $notifiable->prefers_sms ? ['vonage'] : ['mail', 'database'];
9}

佇列通知

在佇列通知之前,您應該設定您的佇列並啟動 worker

發送通知可能需要時間,特別是當管道需要進行外部 API 呼叫來傳遞通知時。為了加快應用程式的回應時間,請將 ShouldQueue 介面和 Queueable trait 新增到您的類別中,讓您的通知排入佇列。介面和 trait 已為使用 make:notification 命令產生的所有通知匯入,因此您可以立即將它們新增到您的通知類別中。

1<?php
2 
3namespace App\Notifications;
4 
5use Illuminate\Bus\Queueable;
6use Illuminate\Contracts\Queue\ShouldQueue;
7use Illuminate\Notifications\Notification;
8 
9class InvoicePaid extends Notification implements ShouldQueue
10{
11 use Queueable;
12 
13 // ...
14}

一旦將 ShouldQueue 介面新增到您的通知,您就可以像平常一樣發送通知。Laravel 將偵測類別上的 ShouldQueue 介面,並自動將通知的傳遞排入佇列。

1$user->notify(new InvoicePaid($invoice));

在佇列通知時,將為每個收件人和管道組合建立一個佇列工作。例如,如果您的通知有三個收件人和兩個管道,則會將六個工作分派到佇列。

延遲通知

如果您想延遲通知的傳遞,您可以將 delay 方法鏈接到您的通知實例化。

1$delay = now()->addMinutes(10);
2 
3$user->notify((new InvoicePaid($invoice))->delay($delay));

您可以將陣列傳遞給 delay 方法,以指定特定管道的延遲時間。

1$user->notify((new InvoicePaid($invoice))->delay([
2 'mail' => now()->addMinutes(5),
3 'sms' => now()->addMinutes(10),
4]));

或者,您可以在通知類別本身上定義 withDelay 方法。withDelay 方法應傳回管道名稱和延遲值的陣列。

1/**
2 * Determine the notification's delivery delay.
3 *
4 * @return array<string, \Illuminate\Support\Carbon>
5 */
6public function withDelay(object $notifiable): array
7{
8 return [
9 'mail' => now()->addMinutes(5),
10 'sms' => now()->addMinutes(10),
11 ];
12}

自訂通知佇列連線

預設情況下,佇列通知將使用您應用程式的預設佇列連線排入佇列。如果您想指定應為特定通知使用的不同連線,您可以從通知的建構函式呼叫 onConnection 方法。

1<?php
2 
3namespace App\Notifications;
4 
5use Illuminate\Bus\Queueable;
6use Illuminate\Contracts\Queue\ShouldQueue;
7use Illuminate\Notifications\Notification;
8 
9class InvoicePaid extends Notification implements ShouldQueue
10{
11 use Queueable;
12 
13 /**
14 * Create a new notification instance.
15 */
16 public function __construct()
17 {
18 $this->onConnection('redis');
19 }
20}

或者,如果您想為通知支援的每個通知管道指定應使用的特定佇列連線,您可以在通知上定義 viaConnections 方法。此方法應傳回管道名稱/佇列連線名稱配對的陣列。

1/**
2 * Determine which connections should be used for each notification channel.
3 *
4 * @return array<string, string>
5 */
6public function viaConnections(): array
7{
8 return [
9 'mail' => 'redis',
10 'database' => 'sync',
11 ];
12}

自訂通知管道佇列

如果您想為通知支援的每個通知管道指定應使用的特定佇列,您可以在通知上定義 viaQueues 方法。此方法應傳回管道名稱/佇列名稱配對的陣列。

1/**
2 * Determine which queues should be used for each notification channel.
3 *
4 * @return array<string, string>
5 */
6public function viaQueues(): array
7{
8 return [
9 'mail' => 'mail-queue',
10 'slack' => 'slack-queue',
11 ];
12}

佇列通知中介層

佇列通知可以定義中介層,就像佇列工作一樣。若要開始使用,請在您的通知類別上定義 middleware 方法。middleware 方法將接收 $notifiable$channel 變數,這讓您可以根據通知的目的地自訂傳回的中介層。

1use Illuminate\Queue\Middleware\RateLimited;
2 
3/**
4 * Get the middleware the notification job should pass through.
5 *
6 * @return array<int, object>
7 */
8public function middleware(object $notifiable, string $channel)
9{
10 return match ($channel) {
11 'email' => [new RateLimited('postmark')],
12 'slack' => [new RateLimited('slack')],
13 default => [],
14 };
15}

佇列通知和資料庫交易

當佇列通知在資料庫交易中分派時,它們可能會在資料庫交易提交之前由佇列處理。發生這種情況時,您在資料庫交易期間對模型或資料庫記錄所做的任何更新可能尚未反映在資料庫中。此外,在交易中建立的任何模型或資料庫記錄可能不存在於資料庫中。如果您的通知依賴這些模型,則在處理發送佇列通知的工作時可能會發生意外錯誤。

如果您的佇列連線的 after_commit 設定選項設定為 false,您仍然可以透過在發送通知時呼叫 afterCommit 方法,指示特定的佇列通知應在所有開啟的資料庫交易提交後分派。

1use App\Notifications\InvoicePaid;
2 
3$user->notify((new InvoicePaid($invoice))->afterCommit());

或者,您可以從通知的建構函式呼叫 afterCommit 方法。

1<?php
2 
3namespace App\Notifications;
4 
5use Illuminate\Bus\Queueable;
6use Illuminate\Contracts\Queue\ShouldQueue;
7use Illuminate\Notifications\Notification;
8 
9class InvoicePaid extends Notification implements ShouldQueue
10{
11 use Queueable;
12 
13 /**
14 * Create a new notification instance.
15 */
16 public function __construct()
17 {
18 $this->afterCommit();
19 }
20}

若要深入瞭解如何解決這些問題,請檢閱有關佇列工作和資料庫交易的文件。

判斷是否應發送佇列通知

在佇列通知分派到佇列以進行背景處理後,它通常會被佇列 worker 接受並發送到其預期的收件者。

但是,如果您想在佇列 worker 處理佇列通知後,最終決定是否應發送該通知,您可以在通知類別上定義 shouldSend 方法。如果此方法傳回 false,則不會發送通知。

1/**
2 * Determine if the notification should be sent.
3 */
4public function shouldSend(object $notifiable, string $channel): bool
5{
6 return $this->invoice->isPaid();
7}

隨需應變通知

有時您可能需要向未儲存為應用程式「使用者」的人員發送通知。使用 Notification facade 的 route 方法,您可以在發送通知之前指定臨時通知路由資訊。

1use Illuminate\Broadcasting\Channel;
2use Illuminate\Support\Facades\Notification;
3 
4Notification::route('mail', '[email protected]')
5 ->route('vonage', '5555555555')
6 ->route('slack', '#slack-channel')
7 ->route('broadcast', [new Channel('channel-name')])
8 ->notify(new InvoicePaid($invoice));

如果您想在向 mail 路由發送隨需應變通知時提供收件者的姓名,您可以提供一個陣列,其中包含電子郵件地址作為索引鍵,姓名作為陣列中第一個元素的值。

1Notification::route('mail', [
2 '[email protected]' => 'Barrett Blair',
3])->notify(new InvoicePaid($invoice));

使用 routes 方法,您可以同時為多個通知管道提供臨時路由資訊。

1Notification::routes([
2 'mail' => ['[email protected]' => 'Barrett Blair'],
3 'vonage' => '5555555555',
4])->notify(new InvoicePaid($invoice));

Mail 通知

格式化 Mail 訊息

如果通知支援以電子郵件形式發送,您應該在通知類別上定義 toMail 方法。此方法將接收一個 $notifiable 實體,並且應傳回 Illuminate\Notifications\Messages\MailMessage 實例。

MailMessage 類別包含一些簡單的方法,可協助您建構交易電子郵件訊息。Mail 訊息可能包含文字行以及「呼叫動作」。讓我們看一下 toMail 方法的範例。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 $url = url('/invoice/'.$this->invoice->id);
7 
8 return (new MailMessage)
9 ->greeting('Hello!')
10 ->line('One of your invoices has been paid!')
11 ->lineIf($this->amount > 0, "Amount paid: {$this->amount}")
12 ->action('View Invoice', $url)
13 ->line('Thank you for using our application!');
14}

請注意,我們在 toMail 方法中使用了 $this->invoice->id。您可以將通知產生訊息所需的任何資料傳遞到通知的建構函式中。

在此範例中,我們註冊了問候語、一行文字、一個呼叫動作,然後是另一行文字。MailMessage 物件提供的這些方法可以簡單快速地格式化小型交易電子郵件。然後,mail 管道會將訊息組件轉換為美觀、回應靈敏的 HTML 電子郵件模板,並具有純文字副本。以下是 mail 管道產生的電子郵件範例。

發送 mail 通知時,請務必在 config/app.php 設定檔中設定 name 設定選項。此值將用於 mail 通知訊息的標頭和標尾中。

錯誤訊息

某些通知會告知使用者錯誤,例如發票付款失敗。您可以在建構訊息時呼叫 error 方法,以指示 mail 訊息與錯誤相關。在 mail 訊息上使用 error 方法時,呼叫動作按鈕將為紅色而不是黑色。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->error()
8 ->subject('Invoice Payment Failed')
9 ->line('...');
10}

其他 Mail 通知格式化選項

除了在通知類別中定義文字「行」之外,您還可以透過使用 view 方法來指定應用於呈現通知電子郵件的自訂模板。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)->view(
7 'mail.invoice.paid', ['invoice' => $this->invoice]
8 );
9}

您可以透過將視圖名稱作為陣列的第二個元素傳遞給 view 方法,來指定 mail 訊息的純文字視圖。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)->view(
7 ['mail.invoice.paid', 'mail.invoice.paid-text'],
8 ['invoice' => $this->invoice]
9 );
10}

或者,如果您的訊息只有純文字視圖,您可以利用 text 方法。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)->text(
7 'mail.invoice.paid-text', ['invoice' => $this->invoice]
8 );
9}

自訂寄件者

預設情況下,電子郵件的寄件者/寄件者地址在 config/mail.php 設定檔中定義。但是,您可以使用 from 方法指定特定通知的寄件者地址。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->from('[email protected]', 'Barrett Blair')
8 ->line('...');
9}

自訂收件者

透過 mail 管道發送通知時,通知系統會自動在您的可通知實體上尋找 email 屬性。您可以透過在可通知實體上定義 routeNotificationForMail 方法,自訂用於傳遞通知的電子郵件地址。

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Foundation\Auth\User as Authenticatable;
6use Illuminate\Notifications\Notifiable;
7use Illuminate\Notifications\Notification;
8 
9class User extends Authenticatable
10{
11 use Notifiable;
12 
13 /**
14 * Route notifications for the mail channel.
15 *
16 * @return array<string, string>|string
17 */
18 public function routeNotificationForMail(Notification $notification): array|string
19 {
20 // Return email address only...
21 return $this->email_address;
22 
23 // Return email address and name...
24 return [$this->email_address => $this->name];
25 }
26}

自訂主旨

預設情況下,電子郵件的主旨是通知的類別名稱,格式為「標題大小寫」。因此,如果您的通知類別命名為 InvoicePaid,則電子郵件的主旨將為 Invoice Paid。如果您想為訊息指定不同的主旨,您可以在建構訊息時呼叫 subject 方法。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->subject('Notification Subject')
8 ->line('...');
9}

自訂 Mailer

預設情況下,電子郵件通知將使用 config/mail.php 設定檔中定義的預設 mailer 發送。但是,您可以在執行階段透過在建構訊息時呼叫 mailer 方法來指定不同的 mailer。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->mailer('postmark')
8 ->line('...');
9}

自訂模板

您可以透過發佈通知套件的資源來修改 mail 通知使用的 HTML 和純文字模板。執行此命令後,mail 通知模板將位於 resources/views/vendor/notifications 目錄中。

1php artisan vendor:publish --tag=laravel-notifications

附件

若要將附件新增至電子郵件通知,請在使用 attach 方法建構訊息時使用。attach 方法接受檔案的絕對路徑作為其第一個引數。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->greeting('Hello!')
8 ->attach('/path/to/file');
9}

通知 mail 訊息提供的 attach 方法也接受可附加物件。請參閱完整的可附加物件文件以瞭解更多資訊。

將檔案附加到訊息時,您也可以透過將 array 作為第二個引數傳遞給 attach 方法來指定顯示名稱和/或 MIME 類型。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->greeting('Hello!')
8 ->attach('/path/to/file', [
9 'as' => 'name.pdf',
10 'mime' => 'application/pdf',
11 ]);
12}

與在 mailable 物件中附加檔案不同,您無法使用 attachFromStorage 直接從儲存磁碟附加檔案。您應該改為將 attach 方法與儲存磁碟上檔案的絕對路徑一起使用。或者,您可以從 toMail 方法傳回 mailable

1use App\Mail\InvoicePaid as InvoicePaidMailable;
2 
3/**
4 * Get the mail representation of the notification.
5 */
6public function toMail(object $notifiable): Mailable
7{
8 return (new InvoicePaidMailable($this->invoice))
9 ->to($notifiable->email)
10 ->attachFromStorage('/path/to/file');
11}

在必要時,可以使用 attachMany 方法將多個檔案附加到訊息。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->greeting('Hello!')
8 ->attachMany([
9 '/path/to/forge.svg',
10 '/path/to/vapor.svg' => [
11 'as' => 'Logo.svg',
12 'mime' => 'image/svg+xml',
13 ],
14 ]);
15}

原始資料附件

attachData 方法可用於將原始位元組字串作為附件附加。呼叫 attachData 方法時,您應提供應指派給附件的檔案名稱。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->greeting('Hello!')
8 ->attachData($this->pdf, 'name.pdf', [
9 'mime' => 'application/pdf',
10 ]);
11}

新增標籤和元數據

某些協力廠商電子郵件提供商(例如 Mailgun 和 Postmark)支援訊息「標籤」和「元數據」,可用於對應用程式發送的電子郵件進行分組和追蹤。您可以透過 tagmetadata 方法將標籤和元數據新增至電子郵件訊息。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->greeting('Comment Upvoted!')
8 ->tag('upvote')
9 ->metadata('comment_id', $this->comment->id);
10}

如果您的應用程式正在使用 Mailgun 驅動程式,您可以查閱 Mailgun 的文件以取得有關標籤元數據的更多資訊。同樣,也可以查閱 Postmark 文件以取得有關其對標籤元數據支援的更多資訊。

如果您的應用程式正在使用 Amazon SES 發送電子郵件,您應該使用 metadata 方法將 SES「標籤」附加到訊息。

自訂 Symfony 訊息

MailMessage 類別的 withSymfonyMessage 方法可讓您註冊一個閉包,該閉包將在發送訊息之前使用 Symfony Message 實例來叫用。這讓您有機會在訊息傳遞之前深入自訂訊息。

1use Symfony\Component\Mime\Email;
2 
3/**
4 * Get the mail representation of the notification.
5 */
6public function toMail(object $notifiable): MailMessage
7{
8 return (new MailMessage)
9 ->withSymfonyMessage(function (Email $message) {
10 $message->getHeaders()->addTextHeader(
11 'Custom-Header', 'Header Value'
12 );
13 });
14}

使用 Mailables

如果需要,您可以從通知的 toMail 方法傳回完整的 mailable 物件。當傳回 Mailable 而不是 MailMessage 時,您需要使用 mailable 物件的 to 方法指定訊息收件者。

1use App\Mail\InvoicePaid as InvoicePaidMailable;
2use Illuminate\Mail\Mailable;
3 
4/**
5 * Get the mail representation of the notification.
6 */
7public function toMail(object $notifiable): Mailable
8{
9 return (new InvoicePaidMailable($this->invoice))
10 ->to($notifiable->email);
11}

Mailables 和隨需應變通知

如果您正在發送隨需應變通知,則提供給 toMail 方法的 $notifiable 實例將是 Illuminate\Notifications\AnonymousNotifiable 的實例,它提供了一個 routeNotificationFor 方法,可用於檢索應向其發送隨需應變通知的電子郵件地址。

1use App\Mail\InvoicePaid as InvoicePaidMailable;
2use Illuminate\Notifications\AnonymousNotifiable;
3use Illuminate\Mail\Mailable;
4 
5/**
6 * Get the mail representation of the notification.
7 */
8public function toMail(object $notifiable): Mailable
9{
10 $address = $notifiable instanceof AnonymousNotifiable
11 ? $notifiable->routeNotificationFor('mail')
12 : $notifiable->email;
13 
14 return (new InvoicePaidMailable($this->invoice))
15 ->to($address);
16}

預覽 Mail 通知

在設計 mail 通知模板時,可以像典型的 Blade 模板一樣在瀏覽器中快速預覽呈現的 mail 訊息,這非常方便。因此,Laravel 允許您直接從路由閉包或控制器傳回由 mail 通知產生的任何 mail 訊息。當傳回 MailMessage 時,它將在瀏覽器中呈現和顯示,讓您可以快速預覽其設計,而無需將其發送到實際的電子郵件地址。

1use App\Models\Invoice;
2use App\Notifications\InvoicePaid;
3 
4Route::get('/notification', function () {
5 $invoice = Invoice::find(1);
6 
7 return (new InvoicePaid($invoice))
8 ->toMail($invoice->user);
9});

Markdown Mail 通知

Markdown mail 通知可讓您充分利用 mail 通知的預先建置模板,同時讓您更自由地撰寫更長、自訂的訊息。由於訊息是以 Markdown 撰寫的,因此 Laravel 能夠為訊息呈現美觀、回應靈敏的 HTML 模板,同時也會自動產生純文字副本。

產生訊息

若要產生具有對應 Markdown 模板的通知,您可以使用 make:notification Artisan 命令的 --markdown 選項。

1php artisan make:notification InvoicePaid --markdown=mail.invoice.paid

與所有其他 mail 通知一樣,使用 Markdown 模板的通知應在其通知類別上定義 toMail 方法。但是,請勿使用 lineaction 方法來建構通知,而是使用 markdown 方法來指定應使用的 Markdown 模板名稱。您希望提供給模板的資料陣列可以作為方法的第二個引數傳遞。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 $url = url('/invoice/'.$this->invoice->id);
7 
8 return (new MailMessage)
9 ->subject('Invoice Paid')
10 ->markdown('mail.invoice.paid', ['url' => $url]);
11}

撰寫訊息

Markdown mail 通知結合了 Blade 組件和 Markdown 語法,讓您可以輕鬆地建構通知,同時利用 Laravel 預先製作的通知組件。

1<x-mail::message>
2# Invoice Paid
3 
4Your invoice has been paid!
5 
6<x-mail::button :url="$url">
7View Invoice
8</x-mail::button>
9 
10Thanks,<br>
11{{ config('app.name') }}
12</x-mail::message>

Button 組件

button 組件呈現一個置中的按鈕連結。該組件接受兩個引數:url 和可選的 color。支援的顏色為 primarygreenred。您可以根據需要將任意數量的 button 組件新增到通知中。

1<x-mail::button :url="$url" color="green">
2View Invoice
3</x-mail::button>

Panel 組件

panel 組件在面板中呈現給定的文字區塊,該面板的背景顏色與通知的其餘部分略有不同。這可讓您將注意力吸引到給定的文字區塊。

1<x-mail::panel>
2This is the panel content.
3</x-mail::panel>

Table 組件

table 組件可讓您將 Markdown 表格轉換為 HTML 表格。該組件接受 Markdown 表格作為其內容。使用預設 Markdown 表格對齊語法支援表格欄位對齊。

1<x-mail::table>
2| Laravel | Table | Example |
3| ------------- | :-----------: | ------------: |
4| Col 2 is | Centered | $10 |
5| Col 3 is | Right-Aligned | $20 |
6</x-mail::table>

自訂組件

您可以匯出所有 Markdown 通知組件到您自己的應用程式以進行自訂。若要匯出組件,請使用 vendor:publish Artisan 命令發佈 laravel-mail 資源標籤。

1php artisan vendor:publish --tag=laravel-mail

此命令會將 Markdown mail 組件發佈到 resources/views/vendor/mail 目錄。mail 目錄將包含 htmltext 目錄,每個目錄都包含每個可用組件的各自表示形式。您可以隨意自訂這些組件。

自訂 CSS

匯出組件後,resources/views/vendor/mail/html/themes 目錄將包含一個 default.css 檔案。您可以自訂此檔案中的 CSS,並且您的樣式將自動內嵌在 Markdown 通知的 HTML 表示形式中。

如果您想為 Laravel 的 Markdown 組件建構全新的主題,您可以將 CSS 檔案放在 html/themes 目錄中。在命名並儲存 CSS 檔案後,更新 mail 設定檔的 theme 選項,以符合新主題的名稱。

若要自訂個別通知的主題,您可以在建構通知的 mail 訊息時呼叫 theme 方法。theme 方法接受應在發送通知時使用的主題名稱。

1/**
2 * Get the mail representation of the notification.
3 */
4public function toMail(object $notifiable): MailMessage
5{
6 return (new MailMessage)
7 ->theme('invoice')
8 ->subject('Invoice Paid')
9 ->markdown('mail.invoice.paid', ['url' => $url]);
10}

Database 通知

先決條件

database 通知管道將通知資訊儲存在資料庫表格中。此表格將包含通知類型以及描述通知的 JSON 資料結構等資訊。

您可以查詢表格以在應用程式的使用者介面中顯示通知。但是,在執行此操作之前,您需要建立一個資料庫表格來保存您的通知。您可以使用 make:notifications-table 命令產生具有正確表格結構的遷移

1php artisan make:notifications-table
2 
3php artisan migrate

如果您的可通知模型正在使用UUID 或 ULID 主鍵,您應該將 morphs 方法替換為通知表格遷移中的 uuidMorphsulidMorphs

格式化 Database 通知

如果通知支援儲存在資料庫表格中,您應該在通知類別上定義 toDatabasetoArray 方法。此方法將接收一個 $notifiable 實體,並且應傳回純 PHP 陣列。傳回的陣列將編碼為 JSON 並儲存在 notifications 表格的 data 欄位中。讓我們看一下 toArray 方法的範例。

1/**
2 * Get the array representation of the notification.
3 *
4 * @return array<string, mixed>
5 */
6public function toArray(object $notifiable): array
7{
8 return [
9 'invoice_id' => $this->invoice->id,
10 'amount' => $this->invoice->amount,
11 ];
12}

當通知儲存在應用程式的資料庫中時,type 欄位將會填入通知的類別名稱。但是,您可以透過在通知類別上定義 databaseType 方法來自訂此行為。

1/**
2 * Get the notification's database type.
3 *
4 * @return string
5 */
6public function databaseType(object $notifiable): string
7{
8 return 'invoice-paid';
9}

toDatabasetoArray

toArray 方法也由 broadcast 管道使用,以決定要廣播到 JavaScript 驅動的前端的資料。如果您希望 databasebroadcast 管道具有兩個不同的陣列表示形式,您應該定義 toDatabase 方法而不是 toArray 方法。

存取通知

一旦通知儲存在資料庫中,您需要一種從可通知實體存取它們的便捷方法。Illuminate\Notifications\Notifiable trait(包含在 Laravel 的預設 App\Models\User 模型中)包含一個 notifications Eloquent 關聯,用於傳回實體的通知。若要提取通知,您可以像存取任何其他 Eloquent 關聯一樣存取此方法。預設情況下,通知將依 created_at 時間戳記排序,最近的通知位於集合的開頭。

1$user = App\Models\User::find(1);
2 
3foreach ($user->notifications as $notification) {
4 echo $notification->type;
5}

如果您只想檢索「未讀」通知,您可以使用 unreadNotifications 關聯。同樣,這些通知將依 created_at 時間戳記排序,最近的通知位於集合的開頭。

1$user = App\Models\User::find(1);
2 
3foreach ($user->unreadNotifications as $notification) {
4 echo $notification->type;
5}

若要從 JavaScript 客戶端存取通知,您應該為應用程式定義一個通知控制器,該控制器傳回可通知實體(例如目前使用者)的通知。然後,您可以從 JavaScript 客戶端向該控制器的 URL 發出 HTTP 請求。

將通知標記為已讀

通常,您會在使用者檢視通知時將其標記為「已讀」。Illuminate\Notifications\Notifiable trait 提供了一個 markAsRead 方法,用於更新通知資料庫記錄上的 read_at 欄位。

1$user = App\Models\User::find(1);
2 
3foreach ($user->unreadNotifications as $notification) {
4 $notification->markAsRead();
5}

但是,您可以直接在通知集合上使用 markAsRead 方法,而不是迴圈處理每個通知。

1$user->unreadNotifications->markAsRead();

您也可以使用大量更新查詢將所有通知標記為已讀,而無需從資料庫檢索它們。

1$user = App\Models\User::find(1);
2 
3$user->unreadNotifications()->update(['read_at' => now()]);

您可以 delete 通知以將它們從表格中完全移除。

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

Broadcast 通知

先決條件

在廣播通知之前,您應該設定並熟悉 Laravel 的 事件廣播 服務。事件廣播提供了一種從 JavaScript 驅動的前端對伺服器端 Laravel 事件做出反應的方法。

格式化 Broadcast 通知

broadcast 管道使用 Laravel 的 事件廣播 服務廣播通知,讓您的 JavaScript 驅動的前端可以即時捕獲通知。如果通知支援廣播,您可以在通知類別上定義 toBroadcast 方法。此方法將接收一個 $notifiable 實體,並且應傳回 BroadcastMessage 實例。如果 toBroadcast 方法不存在,則將使用 toArray 方法來收集應廣播的資料。傳回的資料將編碼為 JSON 並廣播到您的 JavaScript 驅動的前端。讓我們看一下 toBroadcast 方法的範例。

1use Illuminate\Notifications\Messages\BroadcastMessage;
2 
3/**
4 * Get the broadcastable representation of the notification.
5 */
6public function toBroadcast(object $notifiable): BroadcastMessage
7{
8 return new BroadcastMessage([
9 'invoice_id' => $this->invoice->id,
10 'amount' => $this->invoice->amount,
11 ]);
12}

廣播佇列設定

所有廣播通知都會排入佇列以進行廣播。如果您想設定用於佇列廣播操作的佇列連線或佇列名稱,您可以使用 BroadcastMessageonConnectiononQueue 方法。

1return (new BroadcastMessage($data))
2 ->onConnection('sqs')
3 ->onQueue('broadcasts');

自訂通知類型

除了您指定的資料外,所有廣播通知還具有一個 type 欄位,其中包含通知的完整類別名稱。如果您想自訂通知 type,您可以在通知類別上定義 broadcastType 方法。

1/**
2 * Get the type of the notification being broadcast.
3 */
4public function broadcastType(): string
5{
6 return 'broadcast.message';
7}

監聽通知

通知將在使用 {notifiable}.{id} 慣例格式化的私人管道上廣播。因此,如果您要向 ID 為 1App\Models\User 實例發送通知,則通知將在 App.Models.User.1 私人管道上廣播。使用 Laravel Echo 時,您可以使用 notification 方法輕鬆地監聽管道上的通知。

1Echo.private('App.Models.User.' + userId)
2 .notification((notification) => {
3 console.log(notification.type);
4 });

自訂通知管道

如果您想自訂實體的廣播通知廣播到的管道,您可以在可通知實體上定義 receivesBroadcastNotificationsOn 方法。

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Broadcasting\PrivateChannel;
6use Illuminate\Foundation\Auth\User as Authenticatable;
7use Illuminate\Notifications\Notifiable;
8 
9class User extends Authenticatable
10{
11 use Notifiable;
12 
13 /**
14 * The channels the user receives notification broadcasts on.
15 */
16 public function receivesBroadcastNotificationsOn(): string
17 {
18 return 'users.'.$this->id;
19 }
20}

SMS 通知

先決條件

在 Laravel 中發送 SMS 通知由 Vonage(前身為 Nexmo)提供支援。在您可以透過 Vonage 發送通知之前,您需要安裝 laravel/vonage-notification-channelguzzlehttp/guzzle 套件。

1composer require laravel/vonage-notification-channel guzzlehttp/guzzle

該套件包含一個設定檔。但是,您不需要將此設定檔匯出到您自己的應用程式。您只需使用 VONAGE_KEYVONAGE_SECRET 環境變數來定義您的 Vonage 公開金鑰和私密金鑰。

在定義金鑰後,您應該設定 VONAGE_SMS_FROM 環境變數,該變數定義預設應從中發送 SMS 訊息的電話號碼。您可以在 Vonage 控制面板中產生此電話號碼。

1VONAGE_SMS_FROM=15556666666

格式化 SMS 通知

如果通知支援以 SMS 形式發送,您應該在通知類別上定義 toVonage 方法。此方法將接收一個 $notifiable 實體,並且應傳回 Illuminate\Notifications\Messages\VonageMessage 實例。

1use Illuminate\Notifications\Messages\VonageMessage;
2 
3/**
4 * Get the Vonage / SMS representation of the notification.
5 */
6public function toVonage(object $notifiable): VonageMessage
7{
8 return (new VonageMessage)
9 ->content('Your SMS message content');
10}

Unicode 內容

如果您的 SMS 訊息將包含 unicode 字元,您應該在建構 VonageMessage 實例時呼叫 unicode 方法。

1use Illuminate\Notifications\Messages\VonageMessage;
2 
3/**
4 * Get the Vonage / SMS representation of the notification.
5 */
6public function toVonage(object $notifiable): VonageMessage
7{
8 return (new VonageMessage)
9 ->content('Your unicode message')
10 ->unicode();
11}

自訂「From」號碼

如果您想從與 VONAGE_SMS_FROM 環境變數指定的電話號碼不同的電話號碼發送某些通知,您可以呼叫 VonageMessage 實例上的 from 方法。

1use Illuminate\Notifications\Messages\VonageMessage;
2 
3/**
4 * Get the Vonage / SMS representation of the notification.
5 */
6public function toVonage(object $notifiable): VonageMessage
7{
8 return (new VonageMessage)
9 ->content('Your SMS message content')
10 ->from('15554443333');
11}

新增客戶端參考

如果您想要追蹤每個使用者、團隊或客戶的成本,您可以將「客戶參考」新增至通知中。Vonage 允許您使用此客戶參考產生報表,以便您更了解特定客戶的簡訊用量。客戶參考可以是任何最多 40 個字元的字串

1use Illuminate\Notifications\Messages\VonageMessage;
2 
3/**
4 * Get the Vonage / SMS representation of the notification.
5 */
6public function toVonage(object $notifiable): VonageMessage
7{
8 return (new VonageMessage)
9 ->clientReference((string) $notifiable->id)
10 ->content('Your SMS message content');
11}

路由 SMS 通知

若要將 Vonage 通知路由到正確的電話號碼,請在您的可通知實體上定義 routeNotificationForVonage 方法

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Foundation\Auth\User as Authenticatable;
6use Illuminate\Notifications\Notifiable;
7use Illuminate\Notifications\Notification;
8 
9class User extends Authenticatable
10{
11 use Notifiable;
12 
13 /**
14 * Route notifications for the Vonage channel.
15 */
16 public function routeNotificationForVonage(Notification $notification): string
17 {
18 return $this->phone_number;
19 }
20}

Slack 通知

先決條件

在傳送 Slack 通知之前,您應該透過 Composer 安裝 Slack 通知管道

1composer require laravel/slack-notification-channel

此外,您必須為您的 Slack 工作區建立一個 Slack 應用程式

如果您只需要將通知傳送到建立應用程式的同一個 Slack 工作區,您應該確保您的應用程式具有 chat:writechat:write.publicchat:write.customize 權限範圍。如果您想要以您的 Slack 應用程式身分傳送訊息,您也應該確保您的應用程式具有 chat:write:bot 權限範圍。這些權限範圍可以從 Slack 內的「OAuth & 權限」應用程式管理分頁新增。

接下來,複製應用程式的「Bot User OAuth Token」(機器人使用者 OAuth 權杖),並將其放置在您應用程式的 services.php 組態檔案中的 slack 組態陣列中。此權杖可以在 Slack 內的「OAuth & 權限」分頁中找到

1'slack' => [
2 'notifications' => [
3 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
4 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
5 ],
6],

應用程式發佈

如果您的應用程式將向屬於您應用程式使用者的外部 Slack 工作區傳送通知,您將需要透過 Slack「發佈」您的應用程式。應用程式發佈可以從您的應用程式在 Slack 內的「管理發佈」分頁進行管理。一旦您的應用程式已發佈,您可以使用 Socialite 來代表您應用程式的使用者取得 Slack Bot 權杖

格式化 Slack 通知

如果通知支援以 Slack 訊息形式傳送,您應該在通知類別上定義 toSlack 方法。此方法將接收一個 $notifiable 實體,並且應該傳回一個 Illuminate\Notifications\Slack\SlackMessage 實例。您可以使用 Slack 的 Block Kit API 建構豐富的通知。以下範例可以在 Slack 的 Block Kit Builder 中預覽

1use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
2use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
3use Illuminate\Notifications\Slack\BlockKit\Composites\ConfirmObject;
4use Illuminate\Notifications\Slack\SlackMessage;
5 
6/**
7 * Get the Slack representation of the notification.
8 */
9public function toSlack(object $notifiable): SlackMessage
10{
11 return (new SlackMessage)
12 ->text('One of your invoices has been paid!')
13 ->headerBlock('Invoice Paid')
14 ->contextBlock(function (ContextBlock $block) {
15 $block->text('Customer #1234');
16 })
17 ->sectionBlock(function (SectionBlock $block) {
18 $block->text('An invoice has been paid.');
19 $block->field("*Invoice No:*\n1000")->markdown();
20 $block->field("*Invoice Recipient:*\n[email protected]")->markdown();
21 })
22 ->dividerBlock()
23 ->sectionBlock(function (SectionBlock $block) {
24 $block->text('Congratulations!');
25 });
26}

使用 Slack 的 Block Kit Builder 範本

您可以提供 Slack 的 Block Kit Builder 產生的原始 JSON 酬載到 usingBlockKitTemplate 方法,而無需使用流暢的訊息建構器方法來建構您的 Block Kit 訊息

1use Illuminate\Notifications\Slack\SlackMessage;
2use Illuminate\Support\Str;
3 
4/**
5 * Get the Slack representation of the notification.
6 */
7public function toSlack(object $notifiable): SlackMessage
8{
9 $template = <<<JSON
10 {
11 "blocks": [
12 {
13 "type": "header",
14 "text": {
15 "type": "plain_text",
16 "text": "Team Announcement"
17 }
18 },
19 {
20 "type": "section",
21 "text": {
22 "type": "plain_text",
23 "text": "We are hiring!"
24 }
25 }
26 ]
27 }
28 JSON;
29 
30 return (new SlackMessage)
31 ->usingBlockKitTemplate($template);
32}

Slack 互動性

Slack 的 Block Kit 通知系統提供了強大的功能來處理使用者互動。若要使用這些功能,您的 Slack 應用程式應啟用「互動性」,並設定指向您應用程式提供的 URL 的「請求 URL」。這些設定可以在 Slack 內的「互動性與捷徑」應用程式管理分頁中管理。

在以下範例中,其使用了 actionsBlock 方法,Slack 將向您的「請求 URL」傳送一個 POST 請求,其中包含點擊按鈕的 Slack 使用者、點擊按鈕的 ID 等酬載。然後您的應用程式可以根據酬載判斷要採取的動作。您也應該驗證請求是否由 Slack 發出

1use Illuminate\Notifications\Slack\BlockKit\Blocks\ActionsBlock;
2use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
3use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
4use Illuminate\Notifications\Slack\SlackMessage;
5 
6/**
7 * Get the Slack representation of the notification.
8 */
9public function toSlack(object $notifiable): SlackMessage
10{
11 return (new SlackMessage)
12 ->text('One of your invoices has been paid!')
13 ->headerBlock('Invoice Paid')
14 ->contextBlock(function (ContextBlock $block) {
15 $block->text('Customer #1234');
16 })
17 ->sectionBlock(function (SectionBlock $block) {
18 $block->text('An invoice has been paid.');
19 })
20 ->actionsBlock(function (ActionsBlock $block) {
21 // ID defaults to "button_acknowledge_invoice"...
22 $block->button('Acknowledge Invoice')->primary();
23 
24 // Manually configure the ID...
25 $block->button('Deny')->danger()->id('deny_invoice');
26 });
27}

確認模組

如果您希望使用者在執行動作之前必須確認,您可以在定義按鈕時調用 confirm 方法。confirm 方法接受訊息和接收 ConfirmObject 實例的閉包

1use Illuminate\Notifications\Slack\BlockKit\Blocks\ActionsBlock;
2use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
3use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
4use Illuminate\Notifications\Slack\BlockKit\Composites\ConfirmObject;
5use Illuminate\Notifications\Slack\SlackMessage;
6 
7/**
8 * Get the Slack representation of the notification.
9 */
10public function toSlack(object $notifiable): SlackMessage
11{
12 return (new SlackMessage)
13 ->text('One of your invoices has been paid!')
14 ->headerBlock('Invoice Paid')
15 ->contextBlock(function (ContextBlock $block) {
16 $block->text('Customer #1234');
17 })
18 ->sectionBlock(function (SectionBlock $block) {
19 $block->text('An invoice has been paid.');
20 })
21 ->actionsBlock(function (ActionsBlock $block) {
22 $block->button('Acknowledge Invoice')
23 ->primary()
24 ->confirm(
25 'Acknowledge the payment and send a thank you email?',
26 function (ConfirmObject $dialog) {
27 $dialog->confirm('Yes');
28 $dialog->deny('No');
29 }
30 );
31 });
32}

檢查 Slack 區塊

如果您想要快速檢查您正在建構的區塊,您可以在 SlackMessage 實例上調用 dd 方法。dd 方法將產生並轉儲一個 URL 到 Slack 的 Block Kit Builder,其中顯示您瀏覽器中酬載和通知的預覽。您可以將 true 傳遞給 dd 方法以轉儲原始酬載

1return (new SlackMessage)
2 ->text('One of your invoices has been paid!')
3 ->headerBlock('Invoice Paid')
4 ->dd();

路由 Slack 通知

若要將 Slack 通知導向到適當的 Slack 團隊和頻道,請在您的可通知模型上定義 routeNotificationForSlack 方法。此方法可以傳回三個值之一

  • null - 將路由延遲到通知本身中設定的頻道。您可以在建構 SlackMessage 時使用 to 方法來設定通知內的頻道。
  • 指定要將通知傳送到的 Slack 頻道的字串,例如 #support-channel
  • SlackRoute 實例,可讓您指定 OAuth 權杖和頻道名稱,例如 SlackRoute::make($this->slack_channel, $this->slack_token)。此方法應用於將通知傳送到外部工作區。

例如,從 routeNotificationForSlack 方法傳回 #support-channel 將把通知傳送到與您應用程式 services.php 組態檔案中 Bot User OAuth 權杖相關聯的工作區中的 #support-channel 頻道

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Foundation\Auth\User as Authenticatable;
6use Illuminate\Notifications\Notifiable;
7use Illuminate\Notifications\Notification;
8 
9class User extends Authenticatable
10{
11 use Notifiable;
12 
13 /**
14 * Route notifications for the Slack channel.
15 */
16 public function routeNotificationForSlack(Notification $notification): mixed
17 {
18 return '#support-channel';
19 }
20}

通知外部 Slack 工作區

在將通知傳送到外部 Slack 工作區之前,您的 Slack 應用程式必須發佈

當然,您通常會希望將通知傳送到屬於您應用程式使用者的 Slack 工作區。若要執行此操作,您首先需要取得使用者的 Slack OAuth 權杖。值得慶幸的是,Laravel Socialite 包含一個 Slack 驅動程式,可讓您輕鬆地使用 Slack 驗證您應用程式的使用者,並取得機器人權杖

一旦您取得機器人權杖並將其儲存在您應用程式的資料庫中,您可以使用 SlackRoute::make 方法將通知路由到使用者的工作區。此外,您的應用程式可能需要提供讓使用者指定應將通知傳送到哪個頻道的機會

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Foundation\Auth\User as Authenticatable;
6use Illuminate\Notifications\Notifiable;
7use Illuminate\Notifications\Notification;
8use Illuminate\Notifications\Slack\SlackRoute;
9 
10class User extends Authenticatable
11{
12 use Notifiable;
13 
14 /**
15 * Route notifications for the Slack channel.
16 */
17 public function routeNotificationForSlack(Notification $notification): mixed
18 {
19 return SlackRoute::make($this->slack_channel, $this->slack_token);
20 }
21}

本地化通知

Laravel 允許您以 HTTP 請求當前語言環境以外的語言環境傳送通知,並且即使通知已排隊,也會記住此語言環境。

為了實現此目的,Illuminate\Notifications\Notification 類別提供了一個 locale 方法來設定所需的語言。當評估通知時,應用程式將變更為此語言環境,然後在評估完成時還原為先前的語言環境

1$user->notify((new InvoicePaid($invoice))->locale('es'));

也可以透過 Notification facade 實現多個可通知條目的本地化

1Notification::locale('es')->send(
2 $users, new InvoicePaid($invoice)
3);

使用者偏好的語言環境

有時,應用程式會儲存每個使用者偏好的語言環境。透過在您的可通知模型上實作 HasLocalePreference 契約,您可以指示 Laravel 在傳送通知時使用此儲存的語言環境

1use Illuminate\Contracts\Translation\HasLocalePreference;
2 
3class User extends Model implements HasLocalePreference
4{
5 /**
6 * Get the user's preferred locale.
7 */
8 public function preferredLocale(): string
9 {
10 return $this->locale;
11 }
12}

一旦您實作了介面,Laravel 將在向模型傳送通知和郵件時自動使用偏好的語言環境。因此,在使用此介面時,無需調用 locale 方法

1$user->notify(new InvoicePaid($invoice));

測試

您可以使用 Notification facade 的 fake 方法來防止傳送通知。通常,傳送通知與您實際測試的程式碼無關。最有可能的是,僅需斷言 Laravel 已被指示傳送給定的通知就足夠了。

在調用 Notification facade 的 fake 方法之後,您可以斷言已指示將通知傳送給使用者,甚至可以檢查通知接收到的資料

1<?php
2 
3use App\Notifications\OrderShipped;
4use Illuminate\Support\Facades\Notification;
5 
6test('orders can be shipped', function () {
7 Notification::fake();
8 
9 // Perform order shipping...
10 
11 // Assert that no notifications were sent...
12 Notification::assertNothingSent();
13 
14 // Assert a notification was sent to the given users...
15 Notification::assertSentTo(
16 [$user], OrderShipped::class
17 );
18 
19 // Assert a notification was not sent...
20 Notification::assertNotSentTo(
21 [$user], AnotherNotification::class
22 );
23 
24 // Assert that a given number of notifications were sent...
25 Notification::assertCount(3);
26});
1<?php
2 
3namespace Tests\Feature;
4 
5use App\Notifications\OrderShipped;
6use Illuminate\Support\Facades\Notification;
7use Tests\TestCase;
8 
9class ExampleTest extends TestCase
10{
11 public function test_orders_can_be_shipped(): void
12 {
13 Notification::fake();
14 
15 // Perform order shipping...
16 
17 // Assert that no notifications were sent...
18 Notification::assertNothingSent();
19 
20 // Assert a notification was sent to the given users...
21 Notification::assertSentTo(
22 [$user], OrderShipped::class
23 );
24 
25 // Assert a notification was not sent...
26 Notification::assertNotSentTo(
27 [$user], AnotherNotification::class
28 );
29 
30 // Assert that a given number of notifications were sent...
31 Notification::assertCount(3);
32 }
33}

您可以將閉包傳遞給 assertSentToassertNotSentTo 方法,以便斷言已傳送通過給定「真值測試」的通知。如果至少傳送了一個通過給定真值測試的通知,則斷言將成功

1Notification::assertSentTo(
2 $user,
3 function (OrderShipped $notification, array $channels) use ($order) {
4 return $notification->order->id === $order->id;
5 }
6);

隨需應變通知

如果您正在測試的程式碼傳送隨需通知,您可以透過 assertSentOnDemand 方法測試是否已傳送隨需通知

1Notification::assertSentOnDemand(OrderShipped::class);

透過將閉包作為第二個引數傳遞給 assertSentOnDemand 方法,您可以判斷是否已將隨需通知傳送到正確的「路由」地址

1Notification::assertSentOnDemand(
2 OrderShipped::class,
3 function (OrderShipped $notification, array $channels, object $notifiable) use ($user) {
4 return $notifiable->routes['mail'] === $user->email;
5 }
6);

Notification Events

通知傳送事件

當通知正在傳送時,Illuminate\Notifications\Events\NotificationSending 事件會由通知系統分派。這包含「可通知」實體和通知實例本身。您可以在您的應用程式內為此事件建立事件監聽器

1use Illuminate\Notifications\Events\NotificationSending;
2 
3class CheckNotificationStatus
4{
5 /**
6 * Handle the given event.
7 */
8 public function handle(NotificationSending $event): void
9 {
10 // ...
11 }
12}

如果 NotificationSending 事件的事件監聽器從其 handle 方法傳回 false,則不會傳送通知

1/**
2 * Handle the given event.
3 */
4public function handle(NotificationSending $event): bool
5{
6 return false;
7}

在事件監聽器內,您可以存取事件上的 notifiablenotificationchannel 屬性,以了解有關通知接收者或通知本身的更多資訊

1/**
2 * Handle the given event.
3 */
4public function handle(NotificationSending $event): void
5{
6 // $event->channel
7 // $event->notifiable
8 // $event->notification
9}

通知已傳送事件

當通知已傳送時,Illuminate\Notifications\Events\NotificationSent 事件會由通知系統分派。這包含「可通知」實體和通知實例本身。您可以在您的應用程式內為此事件建立事件監聽器

1use Illuminate\Notifications\Events\NotificationSent;
2 
3class LogNotification
4{
5 /**
6 * Handle the given event.
7 */
8 public function handle(NotificationSent $event): void
9 {
10 // ...
11 }
12}

在事件監聽器內,您可以存取事件上的 notifiablenotificationchannelresponse 屬性,以了解有關通知接收者或通知本身的更多資訊

1/**
2 * Handle the given event.
3 */
4public function handle(NotificationSent $event): void
5{
6 // $event->channel
7 // $event->notifiable
8 // $event->notification
9 // $event->response
10}

自訂管道

Laravel 隨附了一些通知管道,但您可能想要編寫自己的驅動程式,以透過其他管道傳遞通知。Laravel 使其變得簡單。若要開始,請定義一個包含 send 方法的類別。該方法應接收兩個引數:$notifiable$notification

send 方法內,您可以調用通知上的方法來檢索您的管道理解的訊息物件,然後以您希望的任何方式將通知傳送給 $notifiable 實例

1<?php
2 
3namespace App\Notifications;
4 
5use Illuminate\Notifications\Notification;
6 
7class VoiceChannel
8{
9 /**
10 * Send the given notification.
11 */
12 public function send(object $notifiable, Notification $notification): void
13 {
14 $message = $notification->toVoice($notifiable);
15 
16 // Send notification to the $notifiable instance...
17 }
18}

一旦您的通知管道類別已定義,您可以從任何通知的 via 方法傳回類別名稱。在此範例中,您的通知的 toVoice 方法可以傳回您選擇代表語音訊息的任何物件。例如,您可以定義自己的 VoiceMessage 類別來代表這些訊息

1<?php
2 
3namespace App\Notifications;
4 
5use App\Notifications\Messages\VoiceMessage;
6use App\Notifications\VoiceChannel;
7use Illuminate\Bus\Queueable;
8use Illuminate\Contracts\Queue\ShouldQueue;
9use Illuminate\Notifications\Notification;
10 
11class InvoicePaid extends Notification
12{
13 use Queueable;
14 
15 /**
16 * Get the notification channels.
17 */
18 public function via(object $notifiable): string
19 {
20 return VoiceChannel::class;
21 }
22 
23 /**
24 * Get the voice representation of the notification.
25 */
26 public function toVoice(object $notifiable): VoiceMessage
27 {
28 // ...
29 }
30}