1葵第、簡介
除了支持發(fā)送郵件之外旺隙,Laravel
還支持通過多種傳輸通道發(fā)送通知降盹,這些通道包括郵件措嵌、短信(通過Nexmo)以及Slack等躲叼。通知可以存儲在數(shù)據(jù)庫以便后續(xù)在web界面中顯示。
通常企巢,通知都是很短的枫慷、用于告知用戶應(yīng)用中所發(fā)生事件的消息。例如,如果你在開發(fā)一個(gè)計(jì)費(fèi)應(yīng)用或听,則需要通過郵件或短信等渠道給用戶發(fā)送“賬單支付”通知探孝。
2、創(chuàng)建通知
在Laravel中誉裆,每個(gè)通知都以單獨(dú)類的形式存在(通常存放在app/Notifications
目錄)顿颅,如果在應(yīng)用中沒看到這個(gè)目錄,別擔(dān)心足丢,它將會在你運(yùn)行Artisan命令make:notification
的時(shí)候自動創(chuàng)建:
php artisan make:notification InvoicePaid
該命令會在app/Notifications
目錄下生成一個(gè)新的通知類粱腻,每個(gè)通知類都包含一個(gè)via
方法以及多個(gè)消息構(gòu)建方法(如toMail
或toDatabase
),這些消息構(gòu)建方法用于將通知轉(zhuǎn)化成為特定渠道優(yōu)化的消息斩跌。
3绍些、發(fā)送通知
使用Notifiable Trait
通知可以通過兩種方式發(fā)送:使用Notifiable
trait提供的notify
方法或者使用Notification
門面。首先耀鸦,我們來檢驗(yàn)Notifiable
trait柬批。該trait被默認(rèn)的App\User
模型使用并提供一個(gè)可用于發(fā)送通知的方法:notify
。notify
方法接收一個(gè)通知實(shí)例:
use App\Notifications\InvoicePaid;
$user->notify(new InvoicePaid($invoice));
注:記住揭糕,你可以在任何模型中使用
Illuminate\Notifications\Notifiable
trait萝快,不限于只在User
模型中使用。
使用Notification門面
作為替代方案著角,還可以通過 Notification
門面發(fā)送通知揪漩。這主要在你需要發(fā)送通知給多個(gè)用戶的時(shí)候很有用,要使用這個(gè)門面發(fā)送通知吏口,需要將所有被通知用戶和通知實(shí)例傳遞給 send
方法:
Notification::send($users, new InvoicePaid($invoice));
指定傳輸通道
每個(gè)通知類都有一個(gè) via
方法用于決定通知通過何種通道傳輸奄容,Laravel開箱支持 mail
、 database
产徊、 broadcast
昂勒、 nexmo
以及 slack
通道。
注:如果你想要使用其他傳輸通道舟铜,比如Telegram或Pusher戈盈,參考社區(qū)提供的驅(qū)動:Laravel通知通道網(wǎng)站。
via
方法接收一個(gè) $notifiable
實(shí)例谆刨,用于指定通知被發(fā)送到的類實(shí)例塘娶。你可以使用 $notifiable
來判斷通知通過何種通道傳輸:
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database'];
}
通知隊(duì)列
注:使用通知隊(duì)列前需要配置隊(duì)列并開啟一個(gè)隊(duì)列任務(wù)。
發(fā)送同時(shí)可能是耗時(shí)的痊夭,尤其是通道需要調(diào)用額外的API來傳輸通知刁岸。為了加速應(yīng)用的響應(yīng)時(shí)間,可以讓通知類實(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會自動檢測到 ShouldQueue
接口然后將通知傳輸推送到隊(duì)列:
$user->notify(new InvoicePaid($invoice));
如果你想要延遲通知的傳輸矾踱,可以在加上 delay
方法:
$when = Carbon::now()->addMinutes(10);
$user->notify((new InvoicePaid($invoice))->delay($when));
4、郵件通知
格式化郵件消息
如果通知支持以郵件方式發(fā)送击敌,你需要在通知類上定義一個(gè) toMail
方法介返。該方法會接收一個(gè) $notifiable
實(shí)體并返回Illuminate\Notifications\Messages\MailMessage
實(shí)例。郵件消息可以包含多行文本以及對動作的調(diào)用沃斤,讓我們來看一個(gè)toMail
方法的示例:
/**
* Get the mail representation of the notification.
*
* @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!');
}
注:注意到我們在
message
方法中使用了$this->invoice->id
圣蝎,你可以傳遞任何通知生成消息所需要的數(shù)據(jù)到通知的構(gòu)造器。
在這個(gè)例子中衡瓶,我們注冊了一條問候徘公、一行文本、對動作的調(diào)用以及另一行文本哮针。MailMessage
對象提供的這些方法讓格式化短小的交易郵件變得簡單快捷关面。mail
通道會將消息組件轉(zhuǎn)化為漂亮的、響應(yīng)式的十厢、帶有純文本副本的HTML郵件模板等太。下面是一個(gè)通過mail
通道生成的郵件示例:
注:發(fā)送郵件通知時(shí),確保在配置文件
config/app.php
中設(shè)置了name
的值蛮放,該值將會用在郵件通知消息的頭部和尾部缩抡。
自定義收件人
通過mail
通道發(fā)送通知時(shí),通知系統(tǒ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;
/**
* Route notifications for the mail channel.
*
* @return string
*/
public function routeNotificationForMail()
{
return $this->email_address;
}
}
自定義主題
默認(rèn)情況下瞻想,郵件的主題就是格式為“標(biāo)題化”的通知類名,因此娩嚼,如果通知類被命名為InvoicePaid
蘑险,郵件的主題就是Invoice Paid
,如果你想要為消息指定明確的主題岳悟,可以在構(gòu)建消息的時(shí)候調(diào)用subject
方法:
/**
* Get the mail representation of the notification.
*
* @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è)命令之后,郵件通知模板將會存放到resources/views/vendor/notifications
目錄:
php artisan vendor:publish --tag=laravel-notifications
錯(cuò)誤消息
一些通知會告知用戶錯(cuò)誤信息贵少,例如一次失敗的單據(jù)支付和屎,你可以在構(gòu)建消息的時(shí)候調(diào)用error
方法標(biāo)識郵件消息是一個(gè)錯(cuò)誤消息。當(dāng)在一個(gè)郵件消息上使用error
方法時(shí)春瞬,動作按鈕的顏色將會由藍(lán)色變成紅色:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Message
*/
public function toMail($notifiable)
{
return (new MailMessage)
->error()
->subject('Notification Subject')
->line('...');
}
5、數(shù)據(jù)庫通知
預(yù)備知識
database
通知通道會在數(shù)據(jù)表中存儲通知信息套啤,該表包含諸如通知類型以及用于描述通知的自定義JSON數(shù)據(jù)之類的信息宽气。
你可以在用戶界面中查詢這個(gè)數(shù)據(jù)表來展示通知随常,不過,在此之前萄涯,需要創(chuàng)建數(shù)據(jù)表來保存信息绪氛,你可以使用notifications:table
命令來生成遷移然后生成數(shù)據(jù)表:
php artisan notifications:table
php artisan migrate
格式化數(shù)據(jù)庫通知
如果一個(gè)通知支持存放在數(shù)據(jù)表,則需要在通知類中定義toDatabase
或toArray
方法涝影,該方法接收一個(gè)$notifiable
實(shí)體并返回原生的PHP數(shù)組枣察。返回的數(shù)組會被編碼為JSON格式然后存放到notifications
表的data
字段。讓我們來看一個(gè)toArray
方法的例子:
/**
* Get the array representation of the notification.
*
* @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客戶端燃逻,如果你想要為database
和broadcast
通道提供兩種不同的數(shù)組表示序目,則需要定義一個(gè)toDatabase
方法來取代toArray
方法。
訪問通知
通知被存放到數(shù)據(jù)表之后伯襟,需要在被通知實(shí)體中有一個(gè)便捷的方式來訪問它們猿涨。Laravel默認(rèn)提供的App\User
模型引入的Illuminate\Notifications\Notifiable
trait包含了返回實(shí)體對應(yīng)通知的Eloquent關(guān)聯(lián)關(guān)系方法notifications
,要獲取這些通知姆怪,可以像訪問其它Eloquent關(guān)聯(lián)關(guān)系一樣訪問該關(guān)聯(lián)方法叛赚,默認(rèn)情況下,通知按照created_at
時(shí)間戳排序:
$user = App\User::find(1);
foreach ($user->notifications as $notification) {
echo $notification->type;
}
如果你只想獲取未讀消息稽揭,可使用關(guān)聯(lián)關(guān)系unreadNotifications俺附,同樣,這些通知也按照created_at時(shí)間戳排序:
$user = App\User::find(1);
foreach ($user->unreadNotifications as $notification) {
echo $notification->type;
}
如果你只想獲取未讀消息溪掀,可使用關(guān)聯(lián)關(guān)系unreadNotifications
事镣,同樣,這些通知也按照created_at
時(shí)間戳排序:
$user = App\User::find(1);
foreach ($user->unreadNotifications as $notification) {
echo $notification->type;
}
注:要想從JavaScript客戶端訪問通知膨桥,需要在應(yīng)用中定義一個(gè)通知控制器為指定被通知實(shí)體(比如當(dāng)前用戶)返回通知蛮浑,然后從JavaScript客戶端發(fā)送一個(gè)HTTP請求到控制器對應(yīng)URI。
標(biāo)記通知為已讀
一般情況下只嚣,我們會將用戶瀏覽過的通知標(biāo)記為已讀沮稚,Illuminate\Notifications\Notifiable
trait提供了一個(gè)markAsRead
方法,用于更新對應(yīng)通知數(shù)據(jù)庫紀(jì)錄上的read_at
字段:
$user = App\User::find(1);
foreach ($user->unreadNotifications as $notification) {
$notification->markAsRead();
}
如果覺得循環(huán)便利每個(gè)通知太麻煩册舞,可以直接在通知集合上調(diào)用markAsRead
方法:
$user->unreadNotifications->markAsRead();
還可以使用批量更新方式標(biāo)記通知為已讀蕴掏,無需先從數(shù)據(jù)庫獲取通知:
$user = App\User::find(1);
$user->unreadNotifications()->update(['read_at' => Carbon::now()]);
當(dāng)然,你也可以通過delete
方法從數(shù)據(jù)庫中移除這些通知:
$user->notifications()->delete();
6调鲸、廣播通知
預(yù)備知識
在進(jìn)行廣播通知之前盛杰,需要配置并了解事件廣播,事件廣播為JavaScript客戶端響應(yīng)服務(wù)端事件觸發(fā)鋪平了道路藐石。
格式化廣播通知
broadcast
通道廣播通知使用了Laravel的事件廣播服務(wù)即供,從而允許JavaScript客戶端實(shí)時(shí)捕獲通知。如果通知支持廣播于微,則需要在通知類上定義 toBroadcast
或 toArray
方法逗嫡,該方法接收一個(gè) $notifiable
實(shí)體并返回原生的PHP數(shù)組青自,返回的數(shù)組會編碼成JSON格式然后廣播到JavaScript客戶端。讓我們來看一個(gè) toArray
方法的示例:
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
注:除了指定的數(shù)據(jù)驱证,廣播通知還包含了一個(gè)
type
字段延窜,用于表示通知類名。
toBroadcast Vs. toArray
toArray
方法還可以用于 database
通道以判斷在數(shù)據(jù)表中存儲哪些數(shù)據(jù)抹锄。如果你想要為 database
和 broadcast
通道提供兩種不同的數(shù)組表示方式逆瑞,需要定義一個(gè) toBroadcast
方法來取代 toArray
方法。
監(jiān)聽通知
通知將會以格式化為 {notifiable}.{id}
的形式在私人頻道上廣播伙单,因此获高,如果你要發(fā)送通知到ID為1
的 App\User
實(shí)例,那么該通知將會在私人頻道 App.User.1
上進(jìn)行廣播车份,如果使用了Laravel Echo谋减,可以使用輔助函數(shù) notification
輕松在某個(gè)頻道上監(jiān)聽通知:
Echo.private('App.User.' + userId)
.notification((notification) => {
console.log(notification.type);
});
7、短信(SMS)通知
預(yù)備知識
Laravel基于Nexmo發(fā)送短信通知扫沼,在使用Nexmo發(fā)送通知前出爹,需要安裝Composer包 nexmo/client
并在配置文件 config/services.php
中進(jìn)行少許配置。你可以從拷貝以下示例配置開始:
'nexmo' => [
'key' => env('NEXMO_KEY'),
'secret' => env('NEXMO_SECRET'),
'sms_from' => '15556666666',
],
sms_from
配置項(xiàng)就是你用于發(fā)送短信消息的手機(jī)號碼缎除,你需要在Nexmo控制面板中為應(yīng)用生成一個(gè)手機(jī)號碼严就。
格式化短信通知
如果通知支持以短信方式發(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');
}
自定義來源號碼
如果你要通過與配置文件 config/services.php
中指定的手機(jī)號不同的其他號碼發(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)會自動在被通知實(shí)體上查找 phone_number
屬性轰坊。如果你想要自定義通知被發(fā)送到的手機(jī)號碼铸董,可以在該實(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.
*
* @return string
*/
public function routeNotificationForNexmo()
{
return $this->phone;
}
}
8、Slack通知
預(yù)備知識
在通過Slack發(fā)送通知前肴沫,必須通過Composer安裝Guzzle HTTP庫:
composer require guzzlehttp/guzzle
此外粟害,你還要為Slack組配置一個(gè)“Incoming Webhook”集成。該集成會在你進(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ā)送一行簡單的文本到Slack菱魔,最終創(chuàng)建的消息如下:
Slack附件
你還可以添加“附件”到Slack消息留荔。相對簡單文本消息,附件可以提供更加豐富的格式選擇澜倦。在這個(gè)例子中存谎,我們會發(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.');
});
}
上述代碼會生成如下Slack消息:
附件還允許你指定要呈獻(xiàn)給用戶的數(shù)組數(shù)據(jù)。為了提高可讀性既荚,給定的數(shù)組會以表格形式展示:
/**
* 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:',
]);
});
}
上述代碼會生成如下Slack消息:
自定義發(fā)送者 & 接收者
你可以使用 from
和 to
方法自定義發(fā)送者和接收者, from
方法接收用戶名和 emoji 標(biāo)識符栋艳,而 to
方法接收一個(gè)頻道或用戶名:
/**
* 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')
}
Slack通知路由
要路由Slack通知到適當(dāng)?shù)奈恢们∑福枰诒煌ㄖ膶?shí)體上定義一個(gè) routeNotificationForSlack
方法,這將會返回通知被發(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.
*
* @return string
*/
public function routeNotificationForSlack()
{
return $this->slack_webhook_url;
}
}
9晴叨、通知事件
當(dāng)通知被發(fā)送后,通知系統(tǒng)會觸發(fā) Illuminate\Notifications\Events\NotificationSent
事件矾屯,該事件實(shí)例包含被通知的實(shí)體(如用戶)和通知實(shí)例本身兼蕊。你可以在 EventServiceProvider
中為該事件注冊監(jiān)聽器:
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Illuminate\Notifications\Events\NotificationSent' => [
'App\Listeners\LogNotification',
],
];
注:在
EventServiceProvider
中注冊監(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
}
10排作、自定義頻道
通過上面的介紹牵啦,可見Laravel為我們提供了一大把通知通道,但是如果你想要編寫自己的驅(qū)動以便通過其他通道發(fā)送通知妄痪,也很簡單哈雏。首先定義一個(gè)包含 send
方法的類,該方法接收兩個(gè)參數(shù): $notifiable
和 $notification
:
<?php
namespace App\Channels;
use Illuminate\Notifications\Notification;
class VoiceChannel
{
/**
* Send the given notification.
*
* @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;
/**
* Get the notification channels.
*
* @param mixed $notifiable
* @return array|string
*/
public function via($notifiable)
{
return [VoiceChannel::class];
}
/**
* Get the voice representation of the notification.
*
* @param mixed $notifiable
* @return VoiceMessage
*/
public function toVoice($notifiable)
{
//...
}
}
文章轉(zhuǎn)載自:https://blog.csdn.net/zhangxh1013/article/details/53130490