# 通知
- [簡介](#introduction)
- [創建通知](#creating-notifications)
- [發送通知](#sending-notifications)
- [使用 Notifiable Trait](#using-the-notifiable-trait)
- [使用 Notification Facade](#using-the-notification-facade)
- [指定發送頻道](#specifying-delivery-channels)
- [隊列化通知](#queueing-notifications)
- [郵件通知](#mail-notifications)
- [格式化郵件消息](#formatting-mail-messages)
- [自定義接受者](#customizing-the-recipient)
- [自定義主題](#customizing-the-subject)
- [自定義模板](#customizing-the-templates)
- [錯誤消息](#error-messages)
- [數據庫通知](#database-notifications)
- [先決條件](#database-prerequisites)
- [格式化數據庫通知](#formatting-database-notifications)
- [訪問通知](#accessing-the-notifications)
- [標為已讀](#marking-notifications-as-read)
- [廣播通知](#broadcast-notifications)
- [先決條件](#broadcast-prerequisites)
- [格式化廣播通知](#formatting-broadcast-notifications)
- [監聽通知](#listening-for-notifications)
- [短信通知](#sms-notifications)
- [先決條件](#sms-prerequisites)
- [格式化短信通知](#formatting-sms-notifications)
- [自定義 `From` 號碼](#customizing-the-from-number)
- [路由短信通知](#routing-sms-notifications)
- [Slack 通知](#slack-notifications)
- [先決條件](#slack-prerequisites)
- [格式化 Slack 通知](#formatting-slack-notifications)
- [路由 Slack 通知](#routing-slack-notifications)
- [通知事件](#notification-events)
- [自定義發送頻道](#custom-channels)
<a name="introduction"></a>
## 簡介
除了 [發送郵件](/docs/{{version}}/mail),Laravel 還支持通過多種頻道發送通知,包括郵件、短信(通過 [Nexmo](https://www.nexmo.com/))以及 [Slack](https://slack.com)。通知還能存到數據庫,這樣就能在網頁界面上顯示了。
通常情況下,通知應該是簡短、有信息量的消息來通知用戶你的應用發生了什么。舉例來說,如果你在編寫一個在線交易應用,你應該會通過郵件和短信頻道來給用戶發送一條「賬單已付」的通知。
<a name="creating-notifications"></a>
## 創建通知
Laravel 中一條通知就是一個類(通常存在 `app/Notifications` 文件夾里)。看不到的話不要擔心,運行一下 `make:notification` 命令就能創建了:
php artisan make:notification InvoicePaid
這個命令會在 `app/Notifications` 目錄下生成一個新的通知類。這個類包含 `via` 方法和幾個消息構建方法(比如 `toMail` 或 `toDatabase`),它們會針對指定的渠道把通知轉換過為對應的消息。
<a name="sending-notifications"></a>
## 發送通知
<a name="using-the-notifiable-trait"></a>
### 使用 Notifiable Trait
通知可以通過兩種方法發送: `Notifiable` trait 的 `notify` 方法或 `Notification` [facade](/docs/{{version}}/facades)。首先,我們看下 `Notifiable` trait 。默認的 `App\User` 模型中使用了這個 trait,它包含著一個可以用來發通知的方法:`notify`。它需要一個通知實例做參數:
use App\Notifications\InvoicePaid;
$user->notify(new InvoicePaid($invoice));
> {tip} 記住,你可以在任意模型中使用 `Illuminate\Notifications\Notifiable` trait,而不僅僅是在 `User` 模型中。
<a name="using-the-notification-facade"></a>
### 使用 Notification Facade
另外,你可以通過 `Notification` [facade](/docs/{{version}}facades) 來發送通知。它主要用在當你給多個可接收通知的實體發送通知的時候,比如給用戶集合發通知。要用 facade 發送通知的話,要把可接收通知的實體和通知的實例傳遞給 `send` 方法:
Notification::send($users, new InvoicePaid($invoice));
<a name="specifying-delivery-channels"></a>
### 指定發送頻道
每個通知類都有個 `via` 方法,它決定了通知在哪個頻道上發送。開箱即用的通知頻道有 `mail`, `database`, `broadcast`, `nexmo`, 和 `slack`。
> {tip} 如果你想用其他的頻道比如 Telegram 或者 Pusher ,可以去看下社區驅動的 [Laravel 通知頻道網站](http://laravel-notification-channels.com)
`via` 方法受到一個`$notifiable` 實例,它是接收通知的類實例。你可以用 `$notifiable` 來決定通知用哪個頻道來發送:
/**
* 獲取通知發送頻道
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database'];
}
<a name="queueing-notifications"></a>
### 隊列化通知
> {note} 在隊列化通知前你需要配置隊列,并 [運行隊列處理器](/docs/{{version}}/queues)。
發送通知可能會花很長時間,尤其是發送頻道需要調用外部 API 的時候。要加速應用響應的話,可以通過添加 `ShouldQueue` 接口和 `Queueable` trait 把通知加入隊列。它們兩個在使用 `make:notification` 命令來生成通知文件的時候就已經被導入了,所以你只需要添加到你的通知類就行了:
<?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` 接口,你就能像平常那樣發送通知了。Laravel 會檢測 `ShouldQueue` 接口并自動將通知的發送放入隊列中。
$user->notify(new InvoicePaid($invoice));
如果你想延遲發送,你可以通過 `delay` 方法來鏈式操作你的通知實例。
$when = Carbon::now()->addMinutes(10);
$user->notify((new InvoicePaid($invoice))->delay($when));
<a name="mail-notifications"></a>
## 郵件通知
<a name="formatting-mail-messages"></a>
### 格式化郵件消息
如果一條通知支持以郵件發送,你應該在通知類里定義一個 `toMail` 方法。這個方法將收到一個 `$notifiable` 實體并返回一個 `Illuminate\Notifications\Messages\MailMessage` 實例。郵件消息可以包含多行文本也可以是引導鏈接。我們來看一個 `toMail` 方法的例子:
/**
* 獲取通知的郵件展示方式
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$url = url('/invoice/'.$this->invoice->id);
return (new MailMessage)
->line('One of your invoices has been paid!')
->action('View Invoice', $url)
->line('Thank you for using our application!');
}
> {tip} 注意我們在方法中用了 `$this->invoice->id` ,其實你可以傳遞應用所需要的任何數據來傳遞給通知的構造器。
在這個例子中,我們注冊了一行文本,引導鏈接 ,然后又是一行文本。`MailMessage` 提供的這些方法簡化了對小的事務性的郵件進行格式化操作。郵件頻道將會把這些消息組件轉換成漂亮的響應式的 HTML 郵件模板并附上文本。下面是個 `mail` 頻道生成的郵件示例:
<img src="https://laravel.com/assets/img/notification-example.png" width="551" height="596">
<a name="customizing-the-recipient"></a>
### 自定義接收者
當通過 `mail` 頻道來發送通知的時候,通知系統將會自動尋找你的 notifiable 實體中的 `email` 屬性。你可以通過在實體中定義 `routeNotificationForMail` 方法來自定義郵件地址。
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* 郵件頻道的路由
*
* @return string
*/
public function routeNotificationForMail()
{
return $this->email_address;
}
}
<a name="customizing-the-subject"></a>
### 自定義主題
默認情況下,郵件主題是格式化成了標題格式的通知類的類名。所以如果你對通知類名為 `InvoicePaid`,郵件主題將會是 `Invoice Paid`。如果你想顯式指定消息的主題,你可以在構建消息時調用 `subject` 方法:
/**
* 獲取通知的郵件展示方式
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Notification Subject')
->line('...');
}
<a name="customizing-the-template"></a>
### 自定義模板
你可以通過發布通知包的資源來修改 HTML 模板和純文本模板。運行這個命令后,郵件通知模板就被放在了 `resources/views/vendor/notifications` 文件夾下。
php artisan vendor:publish --tag laravel-notifications
<a name="error-messages"></a>
### 錯誤消息
有些通知是給用戶提示錯誤,比如賬單支付失敗的提示。你可以通過調用 `error` 方法來指定這條郵件消息被當做一個錯誤提示。當郵件消息使用了 `error` 方法后,引導鏈接按鈕會變成紅色而非藍色。
/**
* 獲取通知的郵件展示方式
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Message
*/
public function toMail($notifiable)
{
return (new MailMessage)
->error()
->subject('Notification Subject')
->line('...');
}
<a name="database-notifications"></a>
## 數據庫通知
<a name="database-prerequisites"></a>
### 先決條件
數據庫通知頻道在一張數據表里存儲通知信息。這張表包含了比如通知類型、JSON 格式數據等描述通知的信息。
你可以查詢這張表的內容在應用界面上展示通知。但是在這之前,你需要先創建一個數據表來保存通知。你可以用 `notifications:table` 命令來生成遷移表。
php artisan notifications:table
php artisan migrate
<a name="formatting-database-notifications"></a>
### 格式化數據庫通知
如果通知支持被存儲到數據表中,你應該在通知類中定義一個 `toDatabase` 或 `toArray` 方法。這個方法接收 `$notifiable` 實體參數并返回一個普通的 PHP 數組。這個返回的數組將被轉成 JSON 格式并存儲到通知數據表的 `data` 列。我們來看一個 `toArray` 的例子:
/**
* 獲取通知的數組展示方式
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
#### `toDatabase` Vs. `toArray`
`toArray` 方法在 `broadcast` 頻道也用到了,它用來決定廣播給 JavaScript 客戶端的數據。如果你想在 `database` 和 `broadcast` 頻道中采用兩種不同的數組展示方式,你應該定義 `toDatabase` 方法而非 `toArray` 方法。
<a name="accessing-the-notifications"></a>
### 訪問通知
一旦通知被存到數據庫中,你需要一種方便的方式來從通知實體中訪問它們。 `Illuminate\Notifications\Notifiable` trait 包含一個可以返回這個實體所有通知的 `notifications` Eloquent 關聯。要獲取這些通知,你可以像用其他 Eloquent 關聯一樣來使用這個方法。默認情況下,通知將會以 `created_at` 時間戳來排序:
$user = App\User::find(1);
foreach ($user->notifications as $notification) {
echo $notification->type;
}
如果你只想檢索未讀通知,你可以使用 `unreadNotifications` 關聯。檢索出來的通知也是以 `created_at` 時間戳來排序的:
$user = App\User::find(1);
foreach ($user->unreadNotifications as $notification) {
echo $notification->type;
}
> {tip} 要從 JavaScript 客戶端來訪問通知的話,你應該定義一個通知控制器來給可通知的實體返回通知,比如給當前用戶返回通知。然后你就可以在 JavaScript 客戶端來發起對應 URI 的 HTTP 請求了。
<a name="marking-notifications-as-read"></a>
### 標為已讀
通常情況下,當用戶查看了通知時,你就希望把通知標為已讀。`Illuminate\Notifications\Notifiable` trait 提供了一個 `markAsRead` 方法,它能在對應的數據庫記錄里更新 `read_at` 列:
$user = App\User::find(1);
foreach ($user->unreadNotifications as $notification) {
$notification->markAsRead();
}
你可以使用 `markAsRead` 方法直接操作一個通知集合,而不是一條條遍歷每個通知:
$user->unreadNotifications->markAsRead();
你可以用批量更新的方式來把所有通知標為已讀,而不用在數據庫里檢索:
$user = App\User::find(1);
$user->unreadNotifications()->update(['read_at' => Carbon::now()]);
當然,你可以通過 `delete` 通知來把它們從數據庫刪除:
$user->notifications()->delete();
<a name="broadcast-notifications"></a>
## 廣播通知
<a name="broadcast-prerequisites"></a>
### 先決條件
在廣播通知前,你應該配置并熟悉 Laravel [事件廣播](/docs/{{version}}/broadcasting) 服務。事件廣播提供了一種 JavaScript 客戶端響應服務端 Laravel 事件的機制。
<a name="formatting-broadcast-notifications"></a>
### 格式化廣播通知
`broadcast` 頻道使用 Laravel [事件廣播](/docs/{{version}}/broadcasting) 服務來廣播通知,它使得 JavaScript 客戶端可以實時捕捉通知。如果一條通知支持廣播,你應該在通知類里定義一個 `toBroadcast` 或 `toArray` 方法。這個方法將收到一個 `$notifiable` 實體并返回一個普通的 PHP 數組。返回的數組會被編碼成 JSON 格式并廣播給你的 JavaScript 客戶端。我們來看個 `toArray` 方法的例子:
/**
* 獲取通知的數組展示方式
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
> {tip} 除了你指定的數據外,廣播通知也包含一個 `type` 字段,這個字段包含了通知類的類名。
#### `toBroadcast` Vs. `toArray`
`toArray` 方法在 `database` 頻道中也用到了,這時它決定了哪些數據會存到你的數據表里。如果你想在 `database` 和 `broadcast` 頻道中采用兩種不同的數組展示方式,你應該定義 `toBroadcast` 方法而非 `toArray` 方法。
<a name="listening-for-notifications"></a>
### 監聽通知
通知將會在一個私有頻道里進行廣播,頻道格式為 `{notifiable}.{id}`。所以,如果你給 ID 為 `1` 的 `App\User` 實例發送通知,這個通知就在 `App.User.1` 私有頻道里被發送。當你使用 [Laravel Echo](/docs/{{version}}/broadcasting) 的時候,你可以很簡單地使用 `notification` 輔助函數來監聽一個頻道的通知:
Echo.private('App.User.' + userId)
.notification((notification) => {
console.log(notification.type);
});
<a name="sms-notifications"></a>
## 短信通知
<a name="sms-prerequisites"></a>
### 先決條件
在 Laravel 中發送短信通知是基于 [Nexmo](https://www.nexmo.com/)服務的。在通過 Nexmo 發送短信通知前,你需要安裝 `nexmo/client` Composer 包并在 `config/services.php` 配置文件中添加幾個配置選項。你可以復制下面的配置示例來開始使用:
'nexmo' => [
'key' => env('NEXMO_KEY'),
'secret' => env('NEXMO_SECRET'),
'sms_from' => '15556666666',
],
`sms_from` 選項是短信消息發送者的手機號碼。你可以在 Nexmo 控制面板中生成一個手機號碼。
<a name="formatting-sms-notifications"></a>
### 格式化短信通知
如果通知支持以短信方式發送,你應該在通知類里定義一個 `toNexmo` 方法。這個方法將會收到一個 `$notifiable` 實體并返回一個 `Illuminate\Notifications\Messages\NexmoMessage` 實例:
/**
* 獲取通知的短信展示方式
*
* @param mixed $notifiable
* @return NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your SMS message content');
}
<a name="customizing-the-from-number"></a>
### 自定義 “From” 號碼
如果你想通過一個手機號來發送某些通知,而這個手機號不同于配置文件中指定的話,你可以在 `NexmoMessage` 實例中使用 `from`:
/**
* 獲取通知的短信展示方式
*
* @param mixed $notifiable
* @return NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your SMS message content')
->from('15554443333');
}
<a name="routing-sms-notifications"></a>
### 路由短信通知
當通過 `nexmo` 頻道來發送通知的時候,通知系統會自動尋找通知實體的 `phone_number` 屬性。如果你想自定義通知被發送的手機號碼,你要在通知實體里定義一個 `routeNotificationForNexmo`
方法。
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* Nexmo 頻道的路由通知
*
* @return string
*/
public function routeNotificationForNexmo()
{
return $this->phone;
}
}
<a name="slack-notifications"></a>
## Slack 通知
<a name="slack-prerequisites"></a>
### 先決條件
通過 Slack 發送通知前,你必須通過 Composer 安裝 Guzzle HTTP 庫:
composer require guzzlehttp/guzzle
你還需要給 Slack 組配置 "Incoming Webhook" 。它將提供你使用 [路由 Slack 通知](#routing-slack-notifications)時用到的 URL。
<a name="formatting-slack-notifications"></a>
### 格式化 Slack 通知
如果通知支持被當做 Slack 消息發送,你應該在通知類里定義一個 `toSlack` 方法。這個方法將收到一個 `$notifiable` 實體并且返回一個 `Illuminate\Notifications\Messages\SlackMessage` 實例。Slack 消息可以包含文本內容以及一個 "attachment" 用來格式化額外文本或者字段數組。我們來看個基本的 `toSlack` 例子:
/**
* 獲取通知的 Slack 展示方式
*
* @param mixed $notifiable
* @return SlackMessage
*/
public function toSlack($notifiable)
{
return (new SlackMessage)
->content('One of your invoices has been paid!');
}
這個例子中,我們只發送了一行文本給 Slack,這會創建類似下面的一條消息:
<img src="https://laravel.com/assets/img/basic-slack-notification.png">
#### Slack 附加項 (Attachments)
你可以給 Slack 消息添加 "附加項"。附加項提供了比簡單文本消息更豐富的格式化選項。在這個例子中,我們將發送一條有關應用中異常的錯誤通知,它里面有個可以查看這個異常更多詳情的鏈接:
/**
* 獲取通知的 Slack 展示方式。
*
* @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 消息:
<img src="https://laravel.com/assets/img/basic-slack-attachment.png">
附加項也允許你指定一個應該被展示給用戶的數據的數組。給定的數據將會以表格樣式展示出來,這能方便閱讀:
/**
* 獲取通知的 Slack 展示方式
*
* @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 消息:
<img src="https://laravel.com/assets/img/slack-fields-attachment.png">
<a name="routing-slack-notifications"></a>
### 路由 Slack 通知
要把 Slack 通知路由到正確的位置,你要在通知實體中定義 `routeNotificationForSlack` 方法。它返回通知要被發往的 URL 回調地址。URL 可以通過在 Slack 組里面添加 "Incoming Webhook" 服務來生成。
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* Slack 頻道的通知路由
*
* @return string
*/
public function routeNotificationForSlack()
{
return $this->slack_webhook_url;
}
}
<a name="notification-events"></a>
## 通知事件
當通知發送后,通知系統就會觸發 `Illuminate\Notifications\Events\NotificationSent` 事件。它包含了 "notifiable" 實體和通知實例本身。你應該在 `EventServiceProvider` 中注冊監聽器:
/**
* 應用中的事件監聽映射。
*
* @var array
*/
protected $listen = [
'Illuminate\Notifications\Events\NotificationSent' => [
'App\Listeners\LogNotification',
],
];
> {tip} 注冊完監聽器后,使用 `event:generate` Artisan 命令來快速生成監聽器類。
在事件監聽器中,你可以訪問事件中的 `notifiable`, `notification`, 和 `channel` 屬性,來了解通知接收者和通知本身:
/**
* 處理事件。
*
* @param NotificationSent $event
* @return void
*/
public function handle(NotificationSent $event)
{
// $event->channel
// $event->notifiable
// $event->notification
}
<a name="custom-channels"></a>
## 自定義頻道
Laravel 提供了開箱即用的通知頻道,但是你可能會想編寫自己的驅動來通過其他頻道發送通知。Laravel 很容易實現。首先,定義一個包含 `send` 方法的類。這個方法應該收到兩個參數:`$notifiable` 和 `$notification`:
<?php
namespace App\Channels;
use Illuminate\Notifications\Notification;
class VoiceChannel
{
/**
* 發送給定通知。
*
* @param mixed $notifiable
* @param \Illuminate\Notifications\Notification $notification
* @return void
*/
public function send($notifiable, Notification $notification)
{
$message = $notification->toVoice($notifiable);
// 將通知發送給 $notifiable 實例
}
}
一旦定義了通知頻道類,你應該在所有通知里通過 `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];
}
/**
* 獲取通知的聲音展示方式
* @param mixed $notifiable
* @return VoiceMessage
*/
public function toVoice($notifiable)
{
// ...
}
}
- 說明
- 翻譯說明
- 發行說明
- 升級說明
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- 錯誤與日志
- 開發環境
- HomeStead
- Valet
- 核心概念
- 服務容器
- 服務提供者
- 門面(facades)
- contracts
- HTTP層
- 路由
- 中間件
- CSRF保護
- 控制器
- 請求
- 響應
- Session
- 表單驗證
- 視圖與模板
- 視圖
- Blade模板
- 本地化
- Javascript與CSS
- 入門指南
- laravel-elixir
- 安全
- 用戶認證
- 用戶授權
- 重置密碼
- API授權
- 加密解密
- 哈希
- 綜合話題
- 廣播系統
- 緩存系統
- 事件系統
- 文件存儲
- 郵件發送
- 消息通知
- 隊列
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent集合
- 修改器
- 序列化
- Artisan控制臺
- Artisan 命令行
- 任務調度
- 測試
- 快速入門
- 應用程序測試
- 數據庫測試
- 模擬器
- 官方擴展包
- Cashier交易包
- Envoy 部署工具
- Passport OAuth 認證
- Scout 全文搜索
- Socialite 社交化登錄
- 附錄
- 集合
- 輔助函數
- 擴展包開發
- 交流說明