イントロダクション
メールの送信のサポートに加えて、LaravelはメールやSMS(Vonage経由、以前はNexmoとして知られていました)およびSlackなど、さまざまな配信チャンネルで通知を送信するためのサポートを提供しています。さらに、さまざまなコミュニティが構築した通知チャンネルが作成され、数十の異なるチャンネルで通知を送信できます!通知はWebインターフェイスに表示するため、データベースに保存される場合もあります。
通常、通知はアプリケーションで何かが起きたことをユーザーへ知らせる、短い情報メッセージです。たとえば、課金アプリを作成しているなら、メールとSMSチャンネルで「課金支払い」を送信できます。
通知の生成
Laravelでは、各通知は通常、app/Notifications
ディレクトリに保存される単一のクラスで表します。アプリケーションにこのディレクトリが存在しなくても心配しないでください。make:notification
Artisanコマンドを実行すると作成されます。
php artisan make:notification InvoicePaid
このコマンドは
app/Notifications
ディレクトリに新しい通知クラスを配置します。各通知クラスはvia
メソッドとtoMail
やtoDatabase
などのメッセージ構築メソッドを含み、通知を特定のチャンネルに合わせたメッセージに変換します。
通知の送信
Notifiableトレイトの使用
通知は、Notifiable
トレイトのnotify
メソッドを使用する方法と、Notification
ファサードを使用する方法の2つの方法で送信できます。Notifiable
トレイトは、アプリケーションのApp\Models\User
モデルにデフォルトで含まれています。
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
* @return \Illuminate\Notifications\Message\SlackMessage
}
このトレイトが提供するnotify
メソッドは、通知インスタンスを引数に受けます。
use App\Notifications\InvoicePaid;
$user->notify(new InvoicePaid($invoice));
Note: どのモデルでも
Notifiable
トレイトを使用できることを忘れないでください。User
モデルに含めるだけに限定されません。
Notificationファサードの使用
別のやり方として、Notification
ファサードを介して通知を送信することもできます。このアプローチは、ユーザーのコレクションなど、複数の通知エンティティに通知を送信する必要がある場合に役立ちます。ファサードを使用して通知を送信するには、すべてのnotifiableエンティティと通知インスタンスをsend
メソッドに渡します。
use Illuminate\Support\Facades\Notification;
Notification::send($users, new InvoicePaid($invoice));
sendNow
メソッドを使って通知をすぐに送信することもできます。このメソッドは、通知が
ShouldQueue
インターフェイスを実装していても、通知を直ちに送信します。
Notification::sendNow($developers, new DeploymentCompleted($deployment));
配信チャンネルの指定
すべての通知クラスは、通知を配信するチャンネルを決定する、via
メソッドを持っています。通知はmail
、database
、broadcast
、vonage
、slack
チャンネルへ配信されるでしょう。
Note: TelegramやPusherのような、他の配信チャンネルを利用したい場合は、コミュニティが管理している、Laravel通知チャンネルのWebサイトをご覧ください。
via
メソッドは、通知を送っているクラスのインスタンスである、$notifiable
インスタンスを引数に受け取ります。$notifiable
を使い、通知をどこのチャンネルへ配信するかを判定できます。
/**
* 通知の配信チャンネルを取得
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return $notifiable->prefers_sms ? ['vonage'] : ['mail', 'database'];
}
通知のキューイング
Warning!! 通知をキューへ投入する前に、キューを設定してワーカを起動する必要があります。
通知の送信には時間がかかる場合があります。特に、チャンネルが通知を配信するために外部API呼び出しを行う必要がある場合に当てはまります。アプリケーションのレスポンス時間を短縮するには、クラスにShouldQueue
インターフェイスとQueueable
トレイトを追加して、通知をキューに入れてください。インターフェイスとトレイトは、make:notification
コマンドを使用して生成されたすべての通知であらかじめインポートされているため、すぐに通知クラスに追加できます。
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
// ...
}
ShouldQueue
インターフェイスを通知クラスへ追加したら、通常通りに送信してください。LaravelはクラスのShouldQueue
インターフェイスを見つけ、自動的に通知の配信をキューへ投入します。
$user->notify(new InvoicePaid($invoice));
通知をキュー投入する場合、受信者とチャンネルの組み合わせごとにジョブを作成し、投入します。例えば、通知が3人の受信者と2つのチャンネルを持つ場合、6つのジョブをキューへディスパッチします。
遅延通知
通知の配信を遅らせたい場合、delay
メソッドを通知のインスタンスへチェーンしてください。
$delay = now()->addMinutes(10);
$user->notify((new InvoicePaid($invoice))->delay($delay));
チャンネルごとの遅延通知
特定のチャンネルの遅延量を指定するため、配列をdelay
メソッドに渡せます。
$user->notify((new InvoicePaid($invoice))->delay([
'mail' => now()->addMinutes(5),
'sms' => now()->addMinutes(10),
]));
あるいは、Notificationクラス自体にwithDelay
メソッドを定義することもできます。withDelay
メソッドは、チャンネル名と遅延値の配列を返す必要があります。
/**
* 通知の送信遅延を決める
*
* @param mixed $notifiable
* @return array
*/
public function withDelay($notifiable)
{
return [
'mail' => now()->addMinutes(5),
'sms' => now()->addMinutes(10),
];
}
通知キュー接続のカスタマイズ
キューへ投入した通知は、アプリケーションのデフォルトのキュー接続を使用してキュー投入します。特定の通知に別の接続を使用する必要がある場合は、通知クラスに$connection
プロパティを定義します。
/**
* 通知をキューに入れるときに使用するキュー接続名
*
* @var string
*/
public $connection = 'redis';
もしくは、通知でサポートしている各通知チャンネルで使用する特定のキュー接続を指定したい場合は、自身の通知にviaConnections
メソッドを定義してください。このメソッドは、チャンネル名とキュー接続名のペアの配列を返す必要があります。
/**
* 各通知チャンネルで使用する接続を決定
*
* @return array
*/
public function viaConnections()
{
return [
'mail' => 'redis',
'database' => 'sync',
];
}
通知チャンネルキューのカスタマイズ
各通知チャンネルが使用し、その通知がサポートしている特定のキューを指定する場合、通知へviaQueues
メソッドを定義してください。このメソッドはチャンネル名/キュー名のペアの配列を返してください。
/**
* 各通知チャンネルで使用するキューを判断。
*
* @return array
*/
public function viaQueues()
{
return [
'mail' => 'mail-queue',
'slack' => 'slack-queue',
];
}
キュー投入する通知とデータベーストランザクション
キューへ投入した通知がデータベーストランザクション内でディスパッチされると、データベーストランザクションがコミットされる前にキューによって処理される場合があります。これが発生した場合、データベーストランザクション中にモデルまたはデータベースレコードに加えた更新は、データベースにまだ反映されていない可能性があります。さらに、トランザクション内で作成されたモデルまたはデータベースレコードは、データベースに存在しない可能性があります。通知がこれらのモデルに依存している場合、キューに入れられた通知を送信するジョブが処理されるときに予期しないエラーが発生する可能性があります。
キュー接続のafter_commit
設定オプションがfalse
に設定されている場合でも、通知時にafterCommit
メソッドを呼び出せば、キュー投入する特定の通知をオープンしている全データベーストランザクションをコミットした後に、ディスパッチするよう指定できます。
use App\Notifications\InvoicePaid;
$user->notify((new InvoicePaid($invoice))->afterCommit());
あるいは、通知のコンストラクタから、afterCommit
メソッドを呼び出すこともできます。
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
/**
* 新しいメッセージインスタンスの生成
*
* @return void
*/
public function __construct()
{
$this->afterCommit();
}
}
Note: この問題の回避方法の詳細は、キュー投入されるジョブとデータベーストランザクションに関するドキュメントを確認してください。
キュー投入した通知を送信するか判定
バックグラウンド処理のため、通知をキューへディスパッチすると、通常はキューワーカがそれを受け取り、意図した受信者へ送信します。
しかし、キューワーカが処理した後に、そのキュー投入済み通知を送信すべきか最終的に判断したい場合は、通知クラスにshouldSend
メソッドを定義してください。このメソッドからfalse
を返す場合、通知は送信されません。
/**
* 通知を送信する必要があるかどうか確認
*
* @param mixed $notifiable
* @param string $channel
* @return bool
*/
public function shouldSend($notifiable, $channel)
{
return $this->invoice->isPaid();
}
オンデマンド通知
アプリケーションの「ユーザー」として保存されていない人に通知を送信する必要がある場合があります。Notification
ファサードのroute
メソッドを使用して、通知を送信する前にアドホックな通知ルーティング情報を指定します。
use Illuminate\Broadcasting\Channel;
Notification::route('mail', 'taylor@example.com')
->route('vonage', '5555555555')
->route('slack', 'https://hooks.slack.com/services/...')
->route('broadcast', [new Channel('channel-name')])
->notify(new InvoicePaid($invoice));
オンデマンド通知をmail
ルートへ送信するとき、受信者名を指定したい場合は、メールアドレスをキーとし、名前を配列の最初の要素の値として含む配列を渡してください。
Notification::route('mail', [
'barrett@example.com' => 'Barrett Blair',
])->notify(new InvoicePaid($invoice));
メール通知
メールメッセージのフォーマット
通知が電子メール送信をサポートしている場合は、通知クラスでtoMail
メソッドを定義する必要があります。このメソッドは$notifiable
エンティティを受け取り、Illuminate\Notifications\Messages\MailMessage
インスタンスを返す必要があります。
MailMessage
クラスには、トランザクションメールメッセージの作成に役立ついくつかの簡単なメソッドが含まれています。メールメッセージには、「行動を促すフレーズ」だけでなく、テキスト行も含まれる場合があります。toMail
メソッドの例を見てみましょう。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$url = url('/invoice/'.$this->invoice->id);
return (new MailMessage)
->greeting('Hello!')
->line('課金が支払われました。')
->lineIf($this->amount > 0, "お支払額: {$this->amount}")
->action('インボイス確認', $url)
->line('私達のアプリケーションをご利用いただき、ありがとうございます。');
}
Note:
toMail
メソッドの中で、$this->invoice->id
を使っていることに注意してください。通知メッセージを生成するために必要な情報は、どんなものでも通知のコンストラクタへ渡せます。
この例では、挨拶、テキスト行、行動を促すフレーズ、そして別のテキスト行を登録します。MailMessage
オブジェクトが提供するこれらのメソッドにより、小さなトランザクションメールを簡単かつ迅速にフォーマットできます。次に、メールチャンネルは、メッセージコンポーネントを、平文テキストと対応する美しいレスポンス性の高いHTML電子メールテンプレートに変換します。mail
チャンネルが生成する電子メールの例を次に示します。
Note: メール通知を送信するときは、必ず
config/app.php
設定ファイルでname
設定オプションを設定してください。この値は、メール通知メッセージのヘッダとフッターに使用されます。
エラーメッセージ
通知の中には、請求書の支払いに失敗したなどのエラーをユーザーへ知らせるものがあります。メッセージを作成時に、error
メソッドを呼び出せば、メールメッセージがエラーに関するものであることを示せます。メールメッセージでerror
メソッドを使用すると、アクションの呼び出しボタンが黒ではなく、赤になります。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->error()
->subject('Invoice Payment Failed')
->line('...');
}
その他のメール通知フォーマットオプション
通知クラスの中にテキストの「行(line)」を定義する代わりに、通知メールをレンダするためのカスタムテンプレートをview
メソッドを使い、指定できます。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)->view(
'emails.name', ['invoice' => $this->invoice]
);
}
view
メソッドに与える配列の2番目の要素としてビュー名を渡すことにより、メールメッセージの平文テキストビューを指定できます。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)->view(
['emails.name.html', 'emails.name.plain'],
['invoice' => $this->invoice]
);
}
送信者のカスタマイズ
デフォルトのメール送信者/Fromアドレスは、config/mail.php
設定ファイルで定義されています。しかし、特定の通知でFromアドレスを指定する場合は、from
メソッドで指定します。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->from('barrett@example.com', 'Barrett Blair')
->line('...');
}
受信者のカスタマイズ
mail
チャンネルを介して通知を送信すると、通知システムは通知エンティティのemail
プロパティを自動的に検索します。通知エンティティでrouteNotificationForMail
メソッドを定義することにより、通知の配信に使用される電子メールアドレスをカスタマイズできます。
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
* @return \Illuminate\Notifications\Message\SlackMessage
/**
* メールチャンネルに対する通知をルートする
*
* @param \Illuminate\Notifications\Notification $notification
* @return array|string
*/
public function routeNotificationForMail($notification)
{
// メールアドレスのみを返す場合
return $this->email_address;
// メールアドレスと名前を返す場合
return [$this->email_address => $this->name];
}
}
件名のカスタマイズ
デフォルトでは、電子メールの件名は「タイトルケース」にフォーマットされた通知のクラス名です。したがって、通知クラスの名前がInvoicePaid
の場合、メールの件名はInvoice Paid
になります。メッセージに別の件名を指定する場合は、メッセージを作成するときに「subject」メソッドを呼び出します。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Notification Subject')
->line('...');
}
Mailerのカスタマイズ
デフォルトでは、電子メール通知は、config/mail.php
設定ファイルで定義しているデフォルトのメーラーを使用して送信されます。ただし、メッセージの作成時にmailer
メソッドを呼び出すことにより、実行時に別のメーラーを指定できます。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->mailer('postmark')
->line('...');
}
テンプレートのカスタマイズ
通知パッケージのリソースをリソース公開することにより、メール通知で使用されるHTMLと平文テキストのテンプレートを変更することが可能です。次のコマンドを実行した後、メール通知のテンプレートはresources/views/vendor/notifications
ディレクトリ下に作成されます。
php artisan vendor:publish --tag=laravel-notifications
添付
電子メール通知に添付ファイルを追加するには、メッセージの作成中にattach
メソッドを使用します。attach
メソッドは、ファイルへの絶対パスを最初の引数に受けます。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file');
}
Note: 通知メールメッセージが提供する
attach
メソッドは、Attachableオブジェクトも受け付けます。詳細は、包括的なAttachableオブジェクトのドキュメントを参照してください。
メッセージにファイルを添付するとき、attach
メソッドの第2引数として配列を渡し、表示名やMIMEタイプの指定もできます。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
}
Mailableオブジェクトにファイルを添付するのとは異なり、attachFromStorage
を使用してストレージディスクから直接ファイルを添付することはできません。むしろ、ストレージディスク上のファイルへの絶対パスを指定してattach
メソッドを使用する必要があります。または、toMail
メソッドからmailableを返すこともできます。
use App\Mail\InvoicePaid as InvoicePaidMailable;
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return Mailable
*/
public function toMail($notifiable)
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email)
->attachFromStorage('/path/to/file');
}
必要であれば、attachMany
メソッドを用いて、複数のファイルをメッセージへ添付できます。
/**
* 通知のメール表現を取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->attachMany([
'/path/to/forge.svg',
'/path/to/vapor.svg' => [
'as' => 'Logo.svg',
'mime' => 'image/svg+xml',
],
]);
}
素のデータの添付
attachData
メソッドを使用して、生のバイト文字列を添付ファイルとして添付できます。attachData
メソッドを呼び出すときは、添付ファイルへ割り当てる必要のあるファイル名を指定する必要があります。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}
タグとメタデータの追加
MailgunやPostmarkなどのサードパーティのメールプロバイダは、メッセージの「タグ」や「メタデータ」をサポートしており、アプリケーションから送信されたメールをグループ化し、追跡するため使用できます。タグやメタデータは、tag
メソッドやmetadata
メソッドを使ってメールメッセージへ追加します。
/**
* 通知のメール表現の取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Comment Upvoted!')
->tag('upvote')
->metadata('comment_id', $this->comment->id);
}
Mailgunドライバを使用しているアプリケーションの場合は、タグとメタデータの詳細は、Mailgunのドキュメントを参照してください。同様に、Postmarkのドキュメントのタグとメタデータで、サポートに関するより詳しい情報を得られます。
アプリケーションでAmazon
SESを使用してメール送信する場合、metadata
メソッドを使用して、メッセージへSESのタグを添付する必要があります。
Symfonyメッセージのカスタマイズ
MailMessage
クラスのwithSymfonyMessage
メソッドを使うと、メッセージを送信する前に、Symfonyメッセージインスタンスで呼び出すクロージャを登録できます。これにより、メッセージが配信される前に、メッセージを細かくカスタマイズする機会を提供しています。
use Symfony\Component\Mime\Email;
/**
* 通知のメール表現の取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->withSymfonyMessage(function (Email $message) {
$message->getHeaders()->addTextHeader(
'Custom-Header', 'Header Value'
);
});
}
Mailablesの使用
必要に応じ、通知のtoMail
メソッドから完全なMailableオブジェクトを返せます。MailMessage
の代わりにMaileable
を返すときは、Mailableオブジェクトのto
メソッドを使ってメッセージ受信者を指定する必要があります。
use App\Mail\InvoicePaid as InvoicePaidMailable;
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return Mailable
*/
public function toMail($notifiable)
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email);
}
Mailablesとオンデマンド通知
オンデマンド通知を送信する場合、toMail
メソッドに渡される$notifiable
インスタンスはIlluminate\Notifications\AnonymousNotifiable
インスタンスになります。routeNotificationFor
メソッドは、オンデマンド通知の送信先のメールアドレスを取得するために使用することができます。
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Notifications\AnonymousNotifiable;
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return Mailable
*/
public function toMail($notifiable)
{
$address = $notifiable instanceof AnonymousNotifiable
? $notifiable->routeNotificationFor('mail')
: $notifiable->email;
return (new InvoicePaidMailable($this->invoice))
->to($address);
}
メール通知のプレビュー
メール通知テンプレートを設計するときは、通常のBladeテンプレートのように、レンダリングしたメールメッセージをブラウザですばやくプレビューできると便利です。このため、Laravelはメール通知によって生成したメールメッセージをルートクロージャまたはコントローラから直接返すことができます。MailMessage
が返されると、ブラウザにレンダリングされて表示されるため、実際のメールアドレスに送信しなくてもデザインをすばやくプレビューできます。
use App\Invoice;
use App\Notifications\InvoicePaid;
Route::get('/notification', function () {
$invoice = Invoice::find(1);
return (new InvoicePaid($invoice))
->toMail($invoice->user);
});
Markdownメール通知
Markdownメール通知により、事前に構築したテンプレートとメール通知のコンポーネントの利点をMailable中で利用できます。メッセージをMarkdownで記述すると、Laravelは美しいレスポンシブHTMLテンプレートをレンダすると同時に、自動的に平文テキスト版も生成します。
メッセージ生成
対応するMarkdownテンプレートを指定し、Mailableを生成するには、make:notification
Artisanコマンドを--markdown
オプション付きで使用します。
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
他のすべてのメール通知と同様に、Markdownテンプレートを使用する通知では、通知クラスにtoMail
メソッドを定義する必要があります。ただし、line
メソッドとaction
メソッドを使用して通知を作成する代わりに、markdown
メソッドを使用して使用するMarkdownテンプレートの名前を指定します。テンプレートで使用できるようにするデータの配列は、メソッドの2番目の引数として渡します。
/**
* 通知のメールプレゼンテーションを取得
*
* @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メール通知ではBladeコンポーネントとMarkdown記法が利用でき、メールメッセージを簡単に構築できると同時に、Laravelが用意している通知コンポーネントも活用できます。
<x-mail::message>
# 領収書
領収いたしました。
<x-mail::button :url="$url">
明細を確認
</x-mail::button>
Thanks,<br>
{{ config('app.name') }}
</x-mail::message>
Buttonコンポーネント
ボタンコンポーネントは、中央寄せに配置したボタンリンクをレンダリングします。コンポーネントは、url
とオプションのcolor
の2つの引数を取ります。サポートしている色は、primary
、green
、red
です。通知には、必要なだけボタンコンポーネントを追加できます。
<x-mail::button :url="$url" color="green">
View Invoice
</x-mail::button>
Panelコンポーネント
パネルコンポーネントは、メッセージの他の部分とは少し異なった背景色のパネルの中に、指定されたテキストブロックをレンダします。これにより、指定するテキストに注目を集められます。
<x-mail::panel>
This is the panel content.
</x-mail::panel>
Tableコンポーネント
テーブルコンポーネントは、MarkdownテーブルをHTMLテーブルへ変換します。このコンポーネントはMarkdownテーブルを内容として受け入れます。デフォルトのMarkdownテーブルの記法を使った、文字寄せをサポートしています。
<x-mail::table>
| Laravel | テーブル | 例 |
| ------------- |:-------------:| --------:|
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
</x-mail::table>
コンポーネントカスタマイズ
自身のアプリケーション向きにカスタマイズできるように、Markdown通知コンポーネントはすべてエクスポートできます。コンポーネントをエクスポートするには、vendor:publish
Artisanコマンドを使い、laravel-mail
アセットをリソース公開します。
php artisan vendor:publish --tag=laravel-mail
このコマンドにより、resources/views/vendor/mail
ディレクトリ下にMarkdownメールコンポーネントがリソース公開されます。mail
ディレクトリ下に、html
とtext
ディレクトリがあります。各ディレクトリは名前が示す形式で、利用できるコンポーネントすべてのレスポンシブなプレゼンテーションを持っています。これらのコンポーネントはお好きなよう、自由にカスタマイズしてください。
CSSのカスタマイズ
コンポーネントをエクスポートすると、resources/views/vendor/mail/html/themes
ディレクトリに、default.css
ファイルが用意されます。このファイル中のCSSをカスタマイズすれば、Markdownメール通知変換後のHTML形式の中に、インラインCSSとして自動的に取り込まれます。
LaravelのMarkdownコンポーネントの完全に新しいテーマを作成したい場合は、html/themes
ディレクトリの中にCSSファイルを設置してください。CSSファイルに名前をつけ保存したら、mail
設定ファイルのtheme
オプションを新しいテーマの名前に更新してください。
個別の通知にカスタムテーマを使いたい場合は、通知のメールメッセージを構築する時に、theme
メソッドを呼び出してください。theme
メソッドの引数は、その通知送信で使用するテーマの名前です。
/**
* 通知のメールプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->theme('invoice')
->subject('Invoice Paid')
->markdown('mail.invoice.paid', ['url' => $url]);
}
データベース通知
事前要件
database
通知チャンネルは、通知情報をデータベーステーブルに格納します。このテーブルには、通知タイプや通知を説明するJSONデータ構造などの情報が含まれます。
テーブルにクエリを実行して、アプリケーションのユーザーインターフェイスで通知を表示できます。ただし、その前に、通知を保存しておくデータベーステーブルを作成する必要があります。notifications:table
コマンドを使用して、適切なテーブルスキーマを定義するマイグレーションを生成できます。
php artisan notifications:table
php artisan migrate
データベース通知のフォーマット
通知でデータベーステーブルへの保存をサポートする場合、通知クラスにtoDatabase
かtoArray
メソッドを定義する必要があります。このメソッドは$notifiable
エンティティを受け取り、プレーンなPHP配列を返す必要があります。返された配列はJSONへエンコードされ、notifications
テーブルのdata
カラムに保存されます。toArray
メソッドの例を見てみましょう。
/**
* 通知の配列プレゼンテーションの取得
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
toDatabase
対toArray
toArray
メソッドはbroadcast
チャンネルでも使用され、JavaScriptで駆動するフロントエンドへブロードキャストするデータを決定するため使われます。database
チャンネルとbroadcast
チャンネルに別々な2つの配列表現が必要な場合は、toArray
メソッドの代わりにtoDatabase
メソッドを定義する必要があります。
通知へのアクセス
通知をデータベースへ保存したら、notifiableエンティティからアクセスするための便利な方法が必要になるでしょう。LaravelのデフォルトのApp\Models\User
モデルに含まれているIlluminate\Notifications\Notification
トレイトには、エンティティのために通知を返すnotifications
Eloquentリレーションが含まれています。通知を取得するため、他のEloquentリレーションと同様にこのメソッドにアクセスできます。デフォルトで通知は「created_at」タイムスタンプで並べ替えられ、コレクションの先頭に最新の通知が表示されます。
$user = App\Models\User::find(1);
foreach ($user->notifications as $notification) {
echo $notification->type;
}
「未読」通知のみを取得する場合は、unreadNotifications
リレーションを使用します。この場合も、コレクションの先頭に最新の通知を含むよう、created_at
タイムスタンプで並べ替えられます。
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
echo $notification->type;
}
Note: JavaScriptクライアントから通知にアクセスするには、現在のユーザーなどのnotifiableエンティティの通知を返す、通知コントローラをアプリケーションで定義する必要があります。次に、JavaScriptクライアントからそのコントローラのURLへHTTPリクエストを送信します。
Readとしての通知作成
通常、ユーザーが閲覧したときに、その通知を「既読」とマークするでしょう。Illuminate\Notifications\Notifiable
トレイトは、通知のデータベースレコード上にある、read_at
カラムを更新するmarkAsRead
メソッドを提供しています。
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
$notification->markAsRead();
}
各通知をループで処理する代わりに、markAsRead
メソッドを通知コレクションへ直接使用できます。
$user->unreadNotifications->markAsRead();
データベースから取得せずに、全通知に既読をマークするため、複数更新クエリを使用することもできます。
$user = App\Models\User::find(1);
$user->unreadNotifications()->update(['read_at' => now()]);
テーブルエンティティから通知を削除するために、delete
を使うこともできます。
$user->notifications()->delete();
ブロードキャスト通知
事前要件
通知をブロードキャストする前に、Laravelのイベントブロードキャストサービスを設定して理解しておく必要があります。イベントブロードキャストは、JavaScriptを利用したフロントエンドから送信するサーバサイドのLaravelイベントに対応する方法を提供しています。
ブロードキャスト通知のフォーマット
broadcast
チャンネルは、Laravelのイベントブロードキャストサービスを使用して通知をブロードキャストし、JavaScriptを利用したフロントエンドがリアルタイムで通知をキャッチできるようにします。通知でブロードキャストをサポートする場合は、通知クラスでtoBroadcast
メソッドを定義します。このメソッドは$notify
エンティティを受け取り、BroadcastMessage
インスタンスを返す必要があります。toBroadcast
メソッドが存在しない場合は、toArray
メソッドを使用してブロードキャストする必要のあるデータを収集します。返したデータはJSONへエンコードされ、JavaScriptを利用したフロントエンドにブロードキャストされます。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,
]);
}
ブロードキャストキュー設定
すべてのブロードキャスト通知はキューへ投入されます。ブロードキャスト操作に使用されるキューの接続や名前を設定したい場合は、BroadcastMessage
のonConnection
とonQueue
メソッドを使用してください。
return (new BroadcastMessage($data))
->onConnection('sqs')
->onQueue('broadcasts');
通知タイプのカスタマイズ
指定したデータに加えて、すべてのブロードキャスト通知には、通知の完全なクラス名を含むtype
フィールドもあります。通知のtype
をカスタマイズする場合は、通知クラスでbroadcastType
メソッドを定義します。
use Illuminate\Notifications\Messages\BroadcastMessage;
/**
* ブロードキャストする通知のタイプ
*
* @return string
*/
public function broadcastType()
{
return 'broadcast.message';
}
通知のリッスン
通知は、{notifiable}.{id}
規約を使い、プライベートチャネル形態でブロードキャストされます。つまり、IDが1
のApp\Models\User
インスタンスの通知を送信する場合、その通知はApp.Models.User.1
のプライベートチャンネルにブロードキャストされます。Laravel
Echoを使用すると、notification
メソッドを使用して簡単に、チャンネル上の通知をリッスンできます。
Echo.private('App.Models.User.' + userId)
.notification((notification) => {
console.log(notification.type);
});
通知チャンネルのカスタマイズ
エンティティのブロードキャスト通知がブロードキャストされるチャンネルをカスタマイズする場合は、notifiableエンティティにreceivesBroadcastNotificationsOn
メソッドを定義します。
<?php
namespace App\Models;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
* @return \Illuminate\Notifications\Message\SlackMessage
/**
* ユーザーがブロードキャストされる通知を受け取るチャンネル
*
* @return string
*/
public function receivesBroadcastNotificationsOn()
{
return 'users.'.$this->id;
}
}
SMS通知
事前要件
LaravelでSMS通知を送るには、Vonage(旧Nexmo)を使用します。Vonageで通知を送信する前に、laravel/vonage-notification-channel
とguzzlehttp/guzzle
パッケージをインストールする必要があります。
composer require laravel/vonage-notification-channel guzzlehttp/guzzle
パッケージは、設定ファイルを持っています。しかし、この設定ファイルを自分のアプリケーションにエクスポートする必要はありません。環境変数VONAGE_KEY
とVONAGE_SECRET
を使い、Vonageの公開鍵と秘密鍵を定義するだけです。
キーを定義したら、VONAGE_SMS_FROM
環境変数を設定して、デフォルトでSMSメッセージを送信する電話番号を定義する必要があります。この電話番号はVonageコントロールパネルで生成できます。
VONAGE_SMS_FROM=15556666666
SMS通知のフォーマット
通知のSMS送信をサポートする場合、通知クラスでtoVonage
メソッドを定義する必要があります。このメソッドは$notifiable
エンティティを受け取り、Illuminate\Notifications\Messages\VonageMessage
インスタンスを返す必要があります。
/**
* 通知のVonage/SMS表現を取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\VonageMessage
*/
public function toVonage($notifiable)
{
return (new VonageMessage)
->content('Your SMS message content');
}
Unicodeコンテンツ
SMSメッセージにunicodeが含まれる場合は、VonageMessage
インスタンス作成する時に、unicode
メソッドを呼び出す必要があります。
/**
* 通知のVonage/SMS表現を取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\VonageMessage
*/
public function toVonage($notifiable)
{
return (new VonageMessage)
->content('Your unicode message')
->unicode();
}
発信元電話番号のカスタマイズ
VONAGE_SMS_FROM
環境変数で指定した電話番号とは異なる番号から通知を送りたい場合は、VonageMessage
インスタンスのfrom
メソッドを呼び出します。
/**
* 通知のVonage/SMS表現を取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\VonageMessage
*/
public function toVonage($notifiable)
{
return (new VonageMessage)
->content('Your SMS message content')
->from('15554443333');
}
クライアントリファレンスの追加
ユーザー、チーム、または顧客ごとのコストを追跡したい場合は、通知に「クライアントリファレンス」を追加することができます。Vonageでは、このクライアントリファレンスを使用してレポートを作成することができますので、特定の顧客のSMS使用状況をよりわかりやすく理解することができます。リライアントリファレンスは、40文字以内の任意の文字列です。
/**
* 通知のVonage/SMS表現を取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\VonageMessage
*/
public function toVonage($notifiable)
{
return (new VonageMessage)
->clientReference((string) $notifiable->id)
->content('Your SMS message content');
}
SMS通知のルート指定
Vonageの通知を適切な電話番号に回すには、NotifiableなエンティティにrouteNotificationForVonage
メソッドを定義してください。
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
* @return \Illuminate\Notifications\Message\SlackMessage
/**
* 通知をVonageチャンネルへ回す
*
* @param \Illuminate\Notifications\Notification $notification
* @return string
*/
public function routeNotificationForVonage($notification)
{
return $this->phone_number;
}
}
Slack通知
事前要件
Slackへの通知を送信し始める前に、ComposerによりSlack通知チャンネルをインストールする必要があります。
composer require laravel/slack-notification-channel
チーム用のSlackアプリも作成する必要があります。アプリを作成したら、ワークスペースの「受信Webhook」を設定する必要があります。Slackは更にSlack通知のルーティングに使用できるWebhookのURLも提供します。
Slack通知のフォーマット
通知がSlackメッセージとしての送信をサポートする場合、通知クラスにtoSlack
メソッドを定義する必要があります。このメソッドは$notifiable
エンティティを受け取り、Illuminate\Notifications\Messages\SlackMessage
インスタンスを返す必要があります。Slackメッセージはテキストと同時に、追加テキストのフォーマットか、フィールドの配列を「添付」として含みます。基本的なtoSlack
の例を見てください。
/**
* 通知のSlackプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\SlackMessage
*/
public function toSlack($notifiable)
{
return (new SlackMessage)
->content('請求の一つが支払われました。');
}
Slack添付
Slackメッセージに「添付」を追加することもできます。添付はシンプルなテキストメッセージよりも、リッチなフォーマットのオプションを提供します。以下の例では、アプリケーションで起きた例外についてのエラー通知で、例外についての詳細情報を表示するリンクを含めています。
/**
* 通知のSlackプレゼンテーションを取得
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\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プレゼンテーションを取得
*
* @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:',
]);
});
}
Markdown添付コンテンツ
添付フィールドをMarkdownで構成している場合、markdown
メソッドでSlackへ指定した添付フィールドがMarkdown形式のテキストであるため、パースしてから表示するように指示します。このメソッドが受け取る値は、pretext
、text
、fields
です。Slackの添付形式についての詳細は、Slack
APIドキュメントをご覧ください。
/**
* 通知の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*.')
->markdown(['text']);
});
}
Slack通知のルート指定
Slack通知を適切なSlackチームとチャンネルにルーティングするには、通知エンティティでrouteNotificationForSlack
メソッドを定義します。これは通知の配信先となるWebフックURLを返します。WebフックURLは、Slackチームに「IncomingWebhook」サービスを追加することで生成できます。
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
* @return \Illuminate\Notifications\Message\SlackMessage
/**
* Slackチャンネルに対する通知をルートする
*
* @param \Illuminate\Notifications\Notification $notification
* @return string
*/
public function routeNotificationForSlack($notification)
{
return 'https://hooks.slack.com/services/...';
}
}
通知のローカライズ
Laravelを使用すると、HTTPリクエストの現在のロケール以外のロケールで通知を送信でき、通知をキュー投入する場合でもこのロケールを記憶しています。
このために、Illuminate\Notifications\Notification
クラスは目的の言語を指定するためのlocale
メソッドを提供しています。通知が評価されると、アプリケーションはこのロケールに変更され、評価が完了すると前のロケールに戻ります。
$user->notify((new InvoicePaid($invoice))->locale('es'));
通知可能な複数のエンティティをローカライズするのも、Notification
ファサードにより可能です。
Notification::locale('es')->send(
$users, new InvoicePaid($invoice)
);
ユーザー希望のローケル
ユーザーの希望するローケルをアプリケーションで保存しておくことは良くあります。notifiableモデルでHasLocalePreference
契約を実装すると、通知送信時にこの保存してあるローケルを使用するように、Laravelへ指示できます。
use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference
{
/**
* ユーザーの希望するローケルの取得
*
* @return string
*/
public function preferredLocale()
{
return $this->locale;
}
}
このインターフェイスを実装すると、そのモデルに対しmailableや通知を送信する時に、Laravelは自動的に好みのローケルを使用します。そのため、このインターフェイスを使用する場合、locale
メソッドを呼び出す必要はありません。
$user->notify(new InvoicePaid($invoice));
通知イベント
通知送信前イベント
通知を送信するときは、通知システムが
Illuminate\Notifications\Events\NotificationSending
イベントを発行します。このイベントは、"notifiable
"エンティティと通知インスタンス自体を含んでいます。アプリケーションのEventServiceProvider
でこのイベントのリスナを登録できます。
use App\Listeners\CheckNotificationStatus;
use Illuminate\Notifications\Events\NotificationSending;
/**
* アプリケーションにマップするイベントリスナの登録
*
* @var array
*/
protected $listen = [
NotificationSending::class => [
CheckNotificationStatus::class,
],
];
NotificationSending
イベントのイベントリスナが、そのhandle
メソッドからfalse
を返した場合、通知は送信されません。
use Illuminate\Notifications\Events\NotificationSending;
/**
* イベントの処理
*
* @param \Illuminate\Notifications\Events\NotificationSending $event
* @return void
*/
public function handle(NotificationSending $event)
{
return false;
}
イベントリスナの中では、イベントのnotifiable
、notification
、channel
プロパティへアクセスし、通知先や通知自体の詳細を調べられます。
/**
* イベントの処理
*
* @param \Illuminate\Notifications\Events\NotificationSending $event
* @return void
*/
public function handle(NotificationSending $event)
{
// $event->channel
// $event->notifiable
// $event->notification
}
通知送信後イベント
通知が送信されると通知システムが、Illuminate\Notifications\Events\NotificationSent
イベントを発行します。このイベントは、"notifiable"エンティティと通知インスタンス自体を含んでいます。このイベントのリスナはEventServiceProvider
で登録できます。
use App\Listeners\LogNotification;
use Illuminate\Notifications\Events\NotificationSent;
/**
* アプリケーションにマップするイベントリスナの登録
*
* @var array
*/
protected $listen = [
NotificationSent::class => [
LogNotification::class,
],
];
Note:
EventServiceProvider
でリスナを登録した後に、event:generate
Artisanコマンドを使うと、リスナクラスが素早く生成できます。
イベントリスナ内では、イベントの
notifiable
、notification
、channel
、response
プロパティにアクセスして、通知先や通知自体の詳細を知ることができます。
/**
* イベントの処理
*
* @param \Illuminate\Notifications\Events\NotificationSent $event
* @return void
*/
public function handle(NotificationSent $event)
{
// $event->channel
// $event->notifiable
// $event->notification
// $event->response
}
カスタムチャンネル
Laravelには通知チャンネルがいくつか付属していますが、他のチャンネルを介して通知を配信する独自のドライバを作成することもできます。Laravelではこれをシンプルに実現できます。作成開始するには、send
メソッドを含むクラスを定義します。このメソッドは、$notifying
と$notification
の2つの引数を受け取る必要があります。
send
メソッド内で、通知メソッドを呼び出して、チャンネルが理解できるメッセージオブジェクトを取得し、必要に応じて通知を$notifiable
インスタンスに送信します。
<?php
namespace App\Notifications;
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
メソッドからクラス名を返せます。この例では、通知のtoVoice
メソッドは、ボイスメッセージを表すために選択するどんなオブジェクトも返せます。たとえば、次のメッセージを表すために独自のVoiceMessage
クラスを定義できます。
<?php
namespace App\Notifications;
use App\Notifications\Messages\VoiceMessage;
use App\Notifications\VoiceChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
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)
{
// ...
}
}