消息通知
消息通知
消息通知
簡(jiǎn)介
除了支持 發(fā)送郵件之外,Laravel 還支持通過多種頻道發(fā)送通知,包括郵件、短信 (通過 Nexmo),以及 Slack。通知還能存儲(chǔ)到數(shù)據(jù)庫(kù)以便后續(xù)在 Web 頁(yè)面中顯示。
通常,通知都是簡(jiǎn)短、有信息量的消息,用于通知用戶應(yīng)用中發(fā)生了什么。舉例來說,如果你是在編寫一個(gè)在線交易的應(yīng)用,你應(yīng)該會(huì)通過郵件和短信頻道類給用戶發(fā)送一條 「賬單支付」 的通知。
創(chuàng)建通知
Laravel 中一條通知就是一個(gè)類 (通常存放在 app/Notifications
文件夾下)。看不到的話不要擔(dān)心,運(yùn)行下 make:notification
命令就能創(chuàng)建了:
php artisan make:notification InvoicePaid
這條命令會(huì)在 app/Notifications
目錄下生成一個(gè)新的通知類。這個(gè)類包含 via
方法以及一個(gè)或多個(gè)消息構(gòu)建的方法 (比如 toMail
或者 toDatabase
) ,它們會(huì)針對(duì)指定的渠道把通知轉(zhuǎn)換為對(duì)應(yīng)的消息。
發(fā)送通知
使用 Notifiable Trait
通知可以通過兩種方法發(fā)送:Notifiable
trait 的 notify
方法或 Notification
facade。首先讓我們來探討下使用 trait:
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable{ use Notifiable; }
默認(rèn)的 App\User
模型中使用了這個(gè) trait,它包含著一個(gè)可以用來發(fā)送通知的方法: notify
。 notify
方法需要一個(gè)通知實(shí)例做參數(shù):
use App\Notifications\InvoicePaid; $user->notify(new InvoicePaid($invoice));
{tip} 記住,你可以在任意模型中使用
Illuminate\Notifications\Notifiable
trait,而不僅僅是在User
模型中。
使用 Notification Facade
另外,你可以通過 Notification
facade 來發(fā)送通知。它主要用在當(dāng)你給多個(gè)可接收通知的實(shí)體發(fā)送的時(shí)候,比如給用戶集合發(fā)送通知。使用 Facade 發(fā)送通知的話,要把可以接收通知和通知的實(shí)例傳遞給 send
方法:
Notification::send($users, new InvoicePaid($invoice));
發(fā)送指定頻道
每個(gè)通知類都會(huì)有個(gè) via
方法,它決定了通知會(huì)在哪個(gè)頻道上發(fā)送。開箱即用的頻道有 mail
,database
,broadcast
,nexmo
和 slack
。
{tip} 如果你想使用其他的頻道,比如 Telegram 或者 Pusher,你可以去看下社區(qū)驅(qū)動(dòng)的 Laravel 通知頻道網(wǎng)站。
via
方法接收一個(gè) $notifiable
實(shí)例。這個(gè)實(shí)例將是通知實(shí)際發(fā)送到的類的實(shí)例。你可以用 $notifiable
來決定通知用哪些頻道來發(fā)送:
/** * 獲取通知發(fā)送頻道。 * * @param mixed $notifiable * @return array */ public function via($notifiable){ return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database']; }
通知隊(duì)列
{注:} 使用通知隊(duì)列前需要配置隊(duì)列并 開啟一個(gè)隊(duì)列任務(wù)。
發(fā)送通知可能是耗時(shí)的,尤其是通道需要調(diào)用額外的 API 來傳輸通知。為了加速應(yīng)用的響應(yīng)時(shí)間,可以將通知推送到隊(duì)列中異步發(fā)送,而要實(shí)現(xiàn)推送通知到隊(duì)列,可以讓對(duì)應(yīng)通知類實(shí)現(xiàn) ShouldQueue
接口并使用 Queueable
trait 。 如果通知類是通過 make:notification
命令生成的,那么該接口和 trait 已經(jīng)默認(rèn)導(dǎo)入,你可以快速將它們添加到通知類:
<?php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; class InvoicePaid extends Notification implements ShouldQueue{ use Queueable; // ... }
ShouldQueue
接口被添加到通知類以后,你可以像之前一樣正常發(fā)送通知,Laravel 會(huì)自動(dòng)檢測(cè)到 ShouldQueue
接口然后將通知推送到隊(duì)列:
$user->notify(new InvoicePaid($invoice));
如果你想要延遲通知的發(fā)送,可以在通知實(shí)例后加上 delay
方法:
$when = now()->addMinutes(10); $user->notify((new InvoicePaid($invoice))->delay($when);
按需通知
有時(shí)候你可能需要發(fā)送通知給某個(gè)用戶,但是該用戶不存在于應(yīng)用的用戶系統(tǒng)中,要實(shí)現(xiàn)這一目的,我們使用 Notification::route
方法在發(fā)送通知之前指定特別的通知路由:
Notification::route('mail', 'taylor@example.com') ->route('nexmo', '5555555555') ->notify(new InvoicePaid($invoice));
郵件通知
格式化郵件消息
如果通知支持以郵件方式發(fā)送,你需要在通知類上定義一個(gè) toMail
方法。該方法會(huì)接收一個(gè) $notifiable
實(shí)體并返回 Illuminate\Notifications\Messages\MailMessage
實(shí)例。郵件消息可以包含多行文本以及對(duì)動(dòng)作的調(diào)用,讓我們來看一個(gè) toMail
方法的示例:
/** * 獲取通知對(duì)應(yīng)的郵件。 * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable){ $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->greeting('Hello!') ->line('One of your invoices has been paid!') ->action('View Invoice', $url) ->line('Thank you for using our application!'); }
{注:} 注意到我們?cè)?
toMail
方法中使用了$this->invoice->id
,你可以傳遞任何通知生成消息所需要的數(shù)據(jù)到通知的構(gòu)造器。
在這個(gè)例子中,我們注冊(cè)了一條問候、一行文本、對(duì)動(dòng)作的調(diào)用以及另一行文本。 MailMessage
對(duì)象提供的這些方法讓格式化短小的事務(wù)郵件變得簡(jiǎn)單快捷。mail
通道會(huì)將消息組件轉(zhuǎn)化為美觀的、響應(yīng)式的、帶有純文本副本的 HTML 郵件模板。下面是一個(gè)通過 mail
通道生成的郵件示例:
{注:} 發(fā)送郵件通知時(shí),確保在配置文件
config/app.php
中設(shè)置了name
的值,該值將會(huì)用在郵件通知消息的頭部和尾部。
其他通知格式化選項(xiàng)
除了在通知類中定義多行文本之外,你還可以使用 view
方法來指定一個(gè)自定義的、用于渲染通知郵件的模板:
/** * 獲取通知郵件。 * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable){ return (new MailMessage)->view( 'emails.name', ['invoice' => $this->invoice] ); }
此外,你可以從 toMail
方法中返回一個(gè) 可郵寄對(duì)象 :
use App\Mail\InvoicePaid as Mailable; /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return Mailable */ public function toMail($notifiable){ return (new Mailable($this->invoice))->to($this->user->email); }
錯(cuò)誤消息
一些通知會(huì)告知用戶錯(cuò)誤信息,例如失敗的訂單支付。你可以在構(gòu)建消息的時(shí)候調(diào)用 error
方法來指示該郵件消息表示錯(cuò)誤信息。在郵件消息中使用 error
方法時(shí),動(dòng)作按鈕將會(huì)變成紅色:
/** * 獲取通知郵件。 * * @param mixed $notifiable * @return \Illuminate\Notifications\Message */ public function toMail($notifiable){ return (new MailMessage) ->error() ->subject('Notification Subject') ->line('...'); }
自定義接收人
通過 mail
通道發(fā)送通知時(shí),通知系統(tǒng)會(huì)自動(dòng)在被通知實(shí)體上查找 email
屬性,你可以通過在該實(shí)體上定義一個(gè) routeNotificationForMail
來自定義使用哪個(gè)郵箱地址發(fā)送通知:
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable{ use Notifiable; /** * 郵件通道通知的路由。 * * @param \Illuminate\Notifications\Notification $notification * @return string */ public function routeNotificationForMail($notification) { return $this->email_address; } }
自定義主題
默認(rèn)情況下,郵件的主題就是格式為 「標(biāo)題風(fēng)格」 的通知類名,因此,如果通知類被命名為 InvoicePaid
,郵件的主題就是 Invoice Paid
,如果你想要為消息指定明確的主題,可以在構(gòu)建消息的時(shí)候調(diào)用 subject
方法:
/** * 獲取通知的郵件表示。 * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable){ return (new MailMessage) ->subject('Notification Subject') ->line('...'); }
自定義模板
你可以通過發(fā)布通知擴(kuò)展包的資源來修改郵件通知所使用的 HTML 和純文本模板。運(yùn)行完下面這個(gè)命令之后,郵件通知模板將會(huì)存放到 resources/views/vendor/notifications
目錄:
php artisan vendor:publish --tag=laravel-notifications
Markdown 郵件通知
Markdown 郵件通知允許你利用郵件通知的預(yù)置模板,從而讓你可以自由編寫更長(zhǎng)、更具個(gè)性化的消息。因?yàn)檫@些消息以 Markdown 格式編寫,Laravel 還可以為它們渲染出高顏值、響應(yīng)式的 HTML 模板,同時(shí)自動(dòng)生成純文本的副本。
生成消息
要生成帶有相應(yīng) Markdown 模板的通知,可以在使用 Artisan 命令 make:notification
時(shí)帶上 --markdown
選項(xiàng):
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
和其他郵件通知一樣,使用 Markdown 模板的通知類也要定義一個(gè) toMail
方法。不過,你可以使用 markdown
方法取代構(gòu)造通知的 line
和 action
方法來指定要使用的 Markdown 模板名稱:
/** * 獲取通知的郵件表示。 * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable){ $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->subject('Invoice Paid') ->markdown('mail.invoice.paid', ['url' => $url]); }
編寫消息
Markdown 郵件通知聯(lián)合使用了 Blade 組件和 Markdown 語(yǔ)法,從而讓你在不脫離 Laravel 預(yù)置組件的情況下輕松構(gòu)建通知:
@component('mail::message') # Invoice PaidYour invoice has been paid! @component('mail::button', ['url' => $url]) View Invoice @endcomponent Thanks,<br> {{ config('app.name') }} @endcomponent
按鈕組件
按鈕組件渲染一個(gè)居中的按鈕鏈接。該組件接收兩個(gè)參數(shù), url
和可選的 color
,支持的顏色有 blue
, green
和 red
。你可以添加任意數(shù)量的按鈕組件到消息中:
@component('mail::button', ['url' => $url, 'color' => 'green']) View Invoice @endcomponent
面板組件
面板組件將給定的文字區(qū)塊渲染到一個(gè)面板中,并且有一個(gè)淡淡的背景色與周圍的消息區(qū)分開。適用于需要引起注意的文字區(qū)塊:
@component('mail::panel') This is the panel content. @endcomponent
表格組件
表格組件允許你將一個(gè) Markdown 表格轉(zhuǎn)化為 HTML 表格。該組件接收 Markdown 表格作為其內(nèi)容。表格列對(duì)齊支持使用默認(rèn)的 Markdown 表格列對(duì)齊語(yǔ)法:
@component('mail::table') | Laravel | Table | Example | | ------------- |:-------------:| --------:| | Col 2 is | Centered | $10 | | Col 3 is | Right-Aligned | $20 | @endcomponent
自定義組件
你可以導(dǎo)出所有 Markdown 通知組件到應(yīng)用中進(jìn)行自定義,要導(dǎo)出組件,使用 Artisan 命令 vendor:publish
來發(fā)布 laravel-mail
資源標(biāo)簽:
php artisan vendor:publish --tag=laravel-mail
該命令會(huì)發(fā)布 Markdown 郵件通知組件到 resources/views/vendor/mail
目錄。 mail
目錄包含 html
和 markdown
目錄,每個(gè)子目錄中又包含各自的所有有效組件。你可以按照自己的喜好自由編輯這些組件。
自定義 CSS
導(dǎo)出組件之后, resources/views/vendor/mail/html/themes
目錄將會(huì)包含一個(gè)默認(rèn)的 default.css
文件,你可以在這個(gè)文件中自定義 CSS,這樣 Markdown 通知的 HTML 樣式就會(huì)自動(dòng)調(diào)整。
{注:} 如果你想要為 Markdown 組件構(gòu)建全新的主題,只需在
html/themes
目錄中編寫一個(gè)新的 CSS 文件并修改theme
選項(xiàng)即可。
數(shù)據(jù)庫(kù)通知
預(yù)備知識(shí)
database
通知通道會(huì)在數(shù)據(jù)表中存儲(chǔ)通知信息,該表包含諸如通知類型以及用于描述通知的自定義 JSON 數(shù)據(jù)之類的信息。
你可以在用戶界面中查詢這個(gè)數(shù)據(jù)表來展示通知,不過,在此之前,需要?jiǎng)?chuàng)建數(shù)據(jù)表來保存信息,你可以使用 notifications:table
命令來生成遷移文件然后以此生成相應(yīng)數(shù)據(jù)表:
php artisan notifications:table php artisan migrate
格式化數(shù)據(jù)庫(kù)通知
如果通知支持存入數(shù)據(jù)庫(kù)表,就為通知類需要定義 toDatabase
或 toArray
方法。此方法接受 $notifiable
實(shí)體作參數(shù)并返回原生 PHP 數(shù)組。返回的數(shù)據(jù)將被編碼為 JSON 并存儲(chǔ)到 notifications
表的 data
列。來看一個(gè) toArray
方法示例:
/** * 獲取通知的數(shù)組表示。 * * @param mixed $notifiable * @return array */ public function toArray($notifiable){ return [ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]; }
toDatabase
Vs. toArray
toArray
方法還可以使用 broadcast
通道來判斷哪些數(shù)據(jù)被廣播到 JavaScript 客戶端。如果針對(duì) database
和 broadcast
通道分別有兩個(gè)不同的數(shù)組表示,你需要定義 toDatabase
方法代替 toArray
方法。
訪問通知
一旦通知存入數(shù)據(jù)庫(kù),就需要適當(dāng)?shù)姆椒ㄗ酝ㄖ獙?shí)體訪問它們。 包含在 Lareval 的默認(rèn) App\User
模型帶有 Illuminate\Notifications\Notifiable
trait,它的 notifications
Eloquent 關(guān)聯(lián)方法能返回實(shí)體通知。要獲取通知,可以像其它 Eloquent 關(guān)聯(lián)方法一樣訪問此方法。默認(rèn)情況下,通知按照 created_at
時(shí)間戳排序:
$user = App\User::find(1); foreach ($user->notifications as $notification) { echo $notification->type; }
若要只獲取 「未讀」通知,可以使用 unreadNotifications
關(guān)聯(lián)方法。同樣這些通知按照 created_at
時(shí)間戳排序:
$user = App\User::find(1); foreach ($user->unreadNotifications as $notification) { echo $notification->type; }
{tip} 若要從 JavaScript 客戶端訪問通知,需要為應(yīng)用定義一個(gè)通知控制器,它返回可通知實(shí)體的通知,比如當(dāng)前用戶??梢詮?JavaScript 客戶端向該控制器 URI 發(fā)送 HTTP 請(qǐng)求。
標(biāo)記通知已讀
通常,在用戶閱覽一條通知之后,你會(huì)想將其標(biāo)識(shí)為「已讀」。 Illuminate\Notifications\Notifiable
trait 提供了 markAsRead
方法,它更新數(shù)據(jù)庫(kù)中通知記錄的 read_at
列:
$user = App\User::find(1); foreach ($user->unreadNotifications as $notification) { $notification->markAsRead(); }
可以在通知控制集合上直接使用 markAsRead
方法代替循環(huán)調(diào)用通知:
$user->unreadNotifications->markAsRead();
還可以使用指更新將所有的通知標(biāo)為已讀,而不從數(shù)據(jù)庫(kù)中讀取它們:
$user = App\User::find(1); $user->unreadNotifications()->update(['read_at' => now()]);
可以使用 delete
方法從表中整個(gè)刪除通知:
$user->notifications()->delete();
廣播通知
預(yù)備知識(shí)
廣播通知前,你需要配置和熟悉 Laravel 的 事件廣播 服務(wù)。事件廣播提供了在 JavaScript 客戶端響應(yīng)服務(wù)端觸發(fā) Laravel 事件的方法。
格式化廣播通知
broadcast
通道使用 Laravel 的 event broadcasting 服務(wù)廣播通知,它允許 JavaScript 客戶端實(shí)時(shí)捕獲通知。如果通知支持廣播,你就需要在通知類上定義 toBroadcast
方法。此方法接受 $notifiable
實(shí)體作為參數(shù),并返回 BroadcastMessage
實(shí)例。返回的數(shù)據(jù)將被編碼為 JSON 并廣播給 JavaScript 客戶端。我們來看一個(gè) toBroadcast
方法示例
use Illuminate\Notifications\Messages\BroadcastMessage;/** * 獲取通知的可廣播表示。 * * @param mixed $notifiable * @return BroadcastMessage */ public function toBroadcast($notifiable){ return new BroadcastMessage([ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]); }
廣播隊(duì)列配置
所有的廣播通知都被放入廣播隊(duì)列。想要配置用于廣播操作的隊(duì)列連接或者隊(duì)列名稱,需要使用 BroadcastMessage
的 onConnection
和 onQueue
方法:
return (new BroadcastMessage($data)) ->onConnection('sqs') ->onQueue('broadcasts');
{tip} 除了指定的數(shù)據(jù),廣播通知還包含
type
域,它包括通知類的類名。
監(jiān)聽通知
通知將會(huì)以格式化為 {notifiable}.{id}
的形式在私有頻道上廣播,因此,如果你要發(fā)送通知到 ID 為 1
的 App\User
實(shí)例,那么該通知將會(huì)在私有頻道 App.User.1
上進(jìn)行廣播,如果使用了 Laravel Echo,可以使用輔助函數(shù) notification
輕松在某個(gè)頻道上監(jiān)聽通知:
Echo.private('App.User.' + userId) .notification((notification) => { console.log(notification.type); });
自定義通知通道
如果你想要自定義被通知實(shí)體在某個(gè)通道上接收廣播通知,可以在被通知實(shí)體上定義一個(gè) receivesBroadcastNotificationsOn
方法:
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable{ use Notifiable; /** * 用戶接收廣播通知的通道。 * * @return string */ public function receivesBroadcastNotificationsOn() { return 'users.'.$this->id; } }
短信(SMS)通知
預(yù)備知識(shí)
Laravel 基于 Nexmo 發(fā)送短信通知,在使用 Nexmo 發(fā)送通知前,需要安裝對(duì)應(yīng) Composer 依賴包 laravel/nexmo-notification-channel
:
composer require laravel/nexmo-notification-channel
下一步,你需要在配置文件 config/services.php
中進(jìn)行相應(yīng)配置。你可以參考以下示例配置:
'nexmo' => [ 'key' => env('NEXMO_KEY'), 'secret' => env('NEXMO_SECRET'), 'sms_from' => '15556666666', ],
sms_from
配置項(xiàng)就是你用于發(fā)送短信消息的手機(jī)號(hào)碼,你需要在 Nexmo 控制面板中為應(yīng)用生成一個(gè)手機(jī)號(hào)碼。
格式化短信通知
如果通知支持以短信方式發(fā)送,那么你需要在通知類上定義一個(gè) toNexmo
方法。該方法接收一個(gè) $notifiable
實(shí)體并返回 Illuminate\Notifications\Messages\NexmoMessage
實(shí)例:
/** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * @return NexmoMessage */ public function toNexmo($notifiable){ return (new NexmoMessage) ->content('Your SMS message content'); }
Unicode 內(nèi)容
如果你的短信消息包含 Unicode 字符,需要在構(gòu)造 NexmoMessage
實(shí)例時(shí)調(diào)用 unicode
方法:
/** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * @return NexmoMessage */ public function toNexmo($notifiable){ return (new NexmoMessage) ->content('Your unicode message') ->unicode(); }
自定義 "發(fā)送" 號(hào)碼
如果你要通過與配置文件 config/services.php
中指定的手機(jī)號(hào)不同的其他號(hào)碼發(fā)送通知,可以使用 NexmoMessage
實(shí)例上的 from
方法:
/** * Get the Nexmo / SMS representation of the notification. * * @param mixed $notifiable * @return NexmoMessage */ public function toNexmo($notifiable){ return (new NexmoMessage) ->content('Your SMS message content') ->from('15554443333'); }
短信通知路由
使用 nexmo
通道發(fā)送通知的時(shí)候,通知系統(tǒng)會(huì)自動(dòng)在被通知實(shí)體上查找 phone_number
屬性。如果你想要自定義通知被發(fā)送到的手機(jī)號(hào)碼,可以在該實(shí)體上定義一個(gè) routeNotificationForNexmo
方法:
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable{ use Notifiable; /** * Route notifications for the Nexmo channel. * * @param \Illuminate\Notifications\Notification $notification * @return string */ public function routeNotificationForNexmo($notification) { return $this->phone; } }
Slack 通知
預(yù)備知識(shí)
在通過 Slack 發(fā)送通知前,必須通過 Composer 安裝 Slack 通知通道:
composer require laravel/slack-notification-channel
此外,你還要為 Slack 組配置一個(gè) "Incoming Webhook" 集成。該集成會(huì)在你進(jìn)行 Slack 通知路由 的時(shí)候提供一個(gè) URL。
格式化 Slack 通知
如果通知支持通過 Slack 消息發(fā)送,則需要在通知類上定義一個(gè) toSlack
方法,該方法接收一個(gè) $notifiable
實(shí)體并返回 Illuminate\Notifications\Messages\SlackMessage
實(shí)例,該實(shí)例包含文本內(nèi)容以及格式化額外文本或數(shù)組字段的 “附件”。讓我們來看一個(gè)基本的 toSlack
使用示例:
/** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable){ return (new SlackMessage) ->content('One of your invoices has been paid!'); }
在這個(gè)例子中,我們只發(fā)送一行簡(jiǎn)單的文本到 Slack,最終創(chuàng)建的消息如下:
Customizing The Sender & Recipient
你可以使用 from
和 to
方法自定義發(fā)送者和接收者, from
方法接收一個(gè)用戶名和 emoji 標(biāo)識(shí),而 to
方法接收通道或用戶名:
/** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable){ return (new SlackMessage) ->from('Ghost', ':ghost:') ->to('#other') ->content('This will be sent to #other'); }
還可以使用圖片作為 logo 用以取代 emoji:
/** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable){ return (new SlackMessage) ->from('Laravel') ->image('https://laravel.com/favicon.png') ->content('This will display the Laravel logo next to the message'); }
Slack 附件
你還可以添加 “附件” 到 Slack 消息。相對(duì)簡(jiǎn)單文本消息,附件可以提供更加豐富的格式選擇。在這個(gè)例子中,我們會(huì)發(fā)送一個(gè)在應(yīng)用程序中出現(xiàn)的異常錯(cuò)誤通知,包含查看更多異常細(xì)節(jié)的鏈接:
/** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable){ $url = url('/exceptions/'.$this->exception->id); return (new SlackMessage) ->error() ->content('Whoops! Something went wrong.') ->attachment(function ($attachment) use ($url) { $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was not found.'); }); }
上述代碼會(huì)生成如下 Slack 消息:
附件還允許你指定要呈獻(xiàn)給用戶的數(shù)組數(shù)據(jù)。為了提高可讀性,給定的數(shù)組會(huì)以表格形式展示:
/** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable){ $url = url('/invoices/'.$this->invoice->id); return (new SlackMessage) ->success() ->content('One of your invoices has been paid!') ->attachment(function ($attachment) use ($url) { $attachment->title('Invoice 1322', $url) ->fields([ 'Title' => 'Server Expenses', 'Amount' => '$1,234', 'Via' => 'American Express', 'Was Overdue' => ':-1:', ]); }); }
上述代碼會(huì)生成如下 Slack 消息:
Markdown 附件內(nèi)容
如果一些附件字段包含 Markdown,可以使用 markdown
方法來構(gòu)建 Slack 用以解析并顯示以 Markdown 格式編寫的附件字段,該方法支持的值包括 pretext
、 text
或 fields
。想要了解更多關(guān)于 Slack 格式化的信息,查看 Slack API 文檔:
/** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable){ $url = url('/exceptions/'.$this->exception->id); return (new SlackMessage) ->error() ->content('Whoops! Something went wrong.') ->attachment(function ($attachment) use ($url) { $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was *not found*.') ->markdown(['text']); }); }
Slack 通知路由
要路由 Slack 通知到適當(dāng)?shù)奈恢茫枰诒煌ㄖ膶?shí)體上定義一個(gè) routeNotificationForSlack
方法,這將會(huì)返回通知被發(fā)送到的 Webhook URL。Webhook URL 可通過在 Slack 組上添加一個(gè) "Incoming Webhook" 服務(wù)來生成:
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable{ use Notifiable; /** * Route notifications for the Slack channel. * * @param \Illuminate\Notifications\Notification $notification * @return string */ public function routeNotificationForSlack($notification) { return 'https://hooks.slack.com/services/...'; } }
本地化通知
Laravel 允許您以當(dāng)前語(yǔ)言環(huán)境之外的其他語(yǔ)言發(fā)送通知,并且會(huì)在通知隊(duì)列時(shí)記住該語(yǔ)言環(huán)境。
要實(shí)現(xiàn)這一點(diǎn), Illuminate\Notifications\Notification
類提供了一個(gè) locale
方法來設(shè)置所需的語(yǔ)言。在格式化通知時(shí),應(yīng)用程序?qū)⒏臑榇苏Z(yǔ)言設(shè)置,然后在格式化完成后還原為以前的語(yǔ)言設(shè)置:
$user->notify((new InvoicePaid($invoice))->locale('es'));
多重通知的本地化也可通過 Notification
Facade 實(shí)現(xiàn):
Notification::locale('es')->send($users, new InvoicePaid($invoice));
用戶首選語(yǔ)言區(qū)域設(shè)置
有些情況下,應(yīng)用程序保存了每個(gè)用戶的首選語(yǔ)言區(qū)域設(shè)置。通過在模型上實(shí)現(xiàn) HasLocalePreference
契約,可以指定 Laravel 在發(fā)送通知時(shí)使用用戶保存的首選語(yǔ)言設(shè)置:
use Illuminate\Contracts\Translation\HasLocalePreference; class User extends Model implements HasLocalePreference{ /** * Get the user's preferred locale. * * @return string */ public function preferredLocale() { return $this->locale; } }
實(shí)現(xiàn)接口后,Laravel 將在向模型發(fā)送通知和郵件時(shí)自動(dòng)使用首選區(qū)域設(shè)置。因此,使用此接口時(shí)不需要調(diào)用 locale
方法:
$user->notify(new InvoicePaid($invoice));
通知事件
當(dāng)通知被發(fā)送后,通知系統(tǒng)會(huì)觸發(fā) Illuminate\Notifications\Events\NotificationSent
事件,該事件實(shí)例包含被通知的實(shí)體(如用戶)和通知實(shí)例本身。你可以在 EventServiceProvider
中為該事件注冊(cè)監(jiān)聽器:
/** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'Illuminate\Notifications\Events\NotificationSent' => [ 'App\Listeners\LogNotification', ], ];
{提示} 在
EventServiceProvider
中注冊(cè)監(jiān)聽器之后,使用 Artisan 命令event:generate
可以快速生成監(jiān)聽器類。
在事件監(jiān)聽器中,可以訪問事件的 notifiable
、 notification
和 channel
屬性了解通知接收者和通知本身的更多信息:
/** * Handle the event. * * @param NotificationSent $event * @return void */ public function handle(NotificationSent $event){ // $event->channel // $event->notifiable // $event->notification // $event->response }
自定義通道
Laravel 為我們提供了多種通知通道,但是嘗試編寫自定義通道驅(qū)動(dòng)以通過其他通道發(fā)送通知,也很簡(jiǎn)單。首先定義一個(gè)包含 send
方法的類,該方法接收兩個(gè)參數(shù): $notifiable
和 $notification
:
<?php namespace App\Channels; use Illuminate\Notifications\Notification;class VoiceChannel{ /** * 發(fā)送指定的通知. * * @param mixed $notifiable * @param \Illuminate\Notifications\Notification $notification * @return void */ public function send($notifiable, Notification $notification) { $message = $notification->toVoice($notifiable); // Send notification to the $notifiable instance... } }
一旦通知通道類被定義后,就可以在應(yīng)用中通過 via
方法返回類名:
<?php namespace App\Notifications; use Illuminate\Bus\Queueable; use App\Channels\VoiceChannel; use App\Channels\Messages\VoiceMessage; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; class InvoicePaid extends Notification{ use Queueable; /** * 獲取通知通道. * * @param mixed $notifiable * @return array|string */ public function via($notifiable) { return [VoiceChannel::class]; } /** * 獲取語(yǔ)音表示的通知. * * @param mixed $notifiable * @return VoiceMessage */ public function toVoice($notifiable) { // ... } }