Laravel

通知

イントロダクション

メール送信に加え、LaravelはSMS(Nexmo使用)、Slackなどの、さまざまな複数チャンネルへ渡る通知をサポートしています。通知はWebインターフェイスで表示できるように、データバースに保存することもできます。

通常、通知はアプリケーションで何かが起きたことをユーザへ知らせる、短い情報メッセージです。たとえば、課金アプリを作成しているなら、メールとSMSチャンネルで「課金支払い」を送信できます。

通知の作成

Laravelの各通知は、(通常、app/Notificationsディレクトリに設置される)クラスにより表されます。このディレクトリがアプリケーションで見つからなくても、心配ありません。make:notification Artisanコマンドを実行すると、作成されます。

php artisan make:notification InvoicePaid

このコマンドにより、真新しい通知クラスが、app/Notificationsディレクトリに生成されます。各通知クラスはviaメソッドと、特定のチャンネルに最適化したメッセージへ変換する、いくつかのメッセージ構築メソッド(toMailtoDatabaseなど)を含んでいます。

通知の送信

Notifiableトレイトの使用

通知は2つの方法で送信されます。Notifiableトレイトのnotifyメソッドか、Notificationファサードを使う方法です。最初に、Notifiableトレイトを見ていきましょう。このトレイトは、デフォルトのApp\Userモデルで使用されており、通知を送るためのnotifyメソッドを一つ含んでいます。notifyメソッドは通知インスタンスを受け取ります。

use App\Notifications\InvoicePaid;

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

Tip!! みなさんのどんなモデルであっても、Illuminate\Notifications\Notifiableトレイトを使えることを覚えておきましょう。使用はUserモデルだけに限定されているわけでありません。

Notificationファサードの使用

ほかに、Notificationファサードを使用し、通知を送る方法もあります。これは主にユーザコレクションのような、複数の通知可能エンティティに対し、通知する場合に便利です。ファサードを使い通知するには、sendメソッドへ通知可能エンティティ全部と、通知インスタンスを渡します。

Notification::send($users, new InvoicePaid($invoice));

配信チャンネルの指定

通知を配信するチャンネルを指定するため、すべての通知クラスはviaメソッドを持っています。通知はmaildatabasebroadcastnexmoslackへ送れるようになっています。

Tip!! TelegramやPusherのような、他の配信チャンネルを利用したい場合は、コミュニティが管理している、Laravel Notification Channels websiteをご覧ください。

viaメソッドは、通知を送っているクラスのインスタンスである、$notifiableインスタンスを引数に受け取ります。$notifiableを使い、通知をどこに配信するチャンネルなのかを判定することができます。

/**
 * 通知の配信チャンネルを取得
 *
 * @param  mixed  $notifiable
 * @return array
 */
public function via($notifiable)
{
    return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database'];
}

通知のキューイング

Note: 通知のキューイングを行う前に、キューを設定し、ワーカを起動する必要があります。

通知の送信には時間が取られます。特にそのチャンネルが通知を配信するために、外部のAPIを呼び出す必要がある場合は特にです。アプリケーションのレスポンスタイムを向上させるには、クラスにShouldQueueインターフェイスと、Queueableトレイトを追加し、キューイングしましょう。このインターフェイスとトレイトは、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));

If you would like to delay the deliver of the notification, you may chain the delay method onto your notification instantiation:

$when = Carbon::now()->addMinutes(10);

$user->notify((new InvoicePaid($invoice))->delay($when));

メール通知

メールメッセージのフォーマット

ある通知でメール送信をサポートする場合、通知クラスにtoMailメソッドを定義してください。このメソッドは、$notifiableエンティティを受け取り、Illuminate\Notifications\Messages\MailMessageインスタンスを返す必要があります。メールメッセージはテキスト行と、同時に"call to action"(アクションの呼び出し)を含むことでしょう。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('課金が支払われました。')
                ->action('インボイス確認', $url)
                ->line('私達のアプリケーションをご利用いただき、ありがとうございます。');
}

Tip!! messageメソッドの中で、$this->invoice->idを使っていることに注意してください。通知メッセージを生成するために必要な情報は、どんなものでも通知のコンストラクタへ渡せます。

この例では、挨拶、テキスト行、アクションの呼び出し、別のテキスト行を登録しています。これらのメソッドは、小さなトランザクションメールをシンプルで素早くフォーマットする、MailMessageオブジェクトが提供しています。メールチャンネルはテンプレートにより、メッセージの構成物をきれいでレスポンシブなHTMLメールへ、変換します。平文メールも用意されます。以下はmailチャンネルにより生成されたメールの例です。I

Tip!! メール通知を行うときは、config/app.php設定ファイルのname値を確実に設定してください。この値は、メール通知メッセージのヘッダとフッタで使用されます。

受取人のカスタマイズ

mailチャンネルを使い、通知を送る場合、通知システムは自動的に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;
    }
}

件名のカスタマイズ

デフォルトのメール件名は、通知のクラス名を"title case"にフォーマットしたものです。ですから、InvoicePaidという通知クラス名は、Invoice Paidというメールの件名になります。メッセージの件名を明確に指定したい場合は、メッセージを構築時にsubjectメソッドを呼び出してください。

/**
 * 通知のメールプレゼンテーションを取得
 *
 * @param  mixed  $notifiable
 * @return \Illuminate\Notifications\Messages\MailMessage
 */
public function toMail($notifiable)
{
    return (new MailMessage)
                ->subject('Notification Subject')
                ->line('...');
}

テンプレートのカスタマイズ

通知パッケージのリソースを公開(開発者が変更できる場所にリソースを用意することを示すLaravel用語)することにより、メール通知で使用されるHTMLと平文テキストのテンプレートを変更することが可能です。次のコマンドを実行した後、メール通知のテンプレートはresources/views/vendor/notificationsディレクトリ下に作成されます。

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

エラーメッセージ

ある通知はユーザへエラーを知らせます。たとえば、課金の失敗です。メールメッセージがエラーに関するものであることを知らせるためには、メッセージ構築時にerrorメソッドを呼び出します。errorメソッドをメールメッセージで使用すると、アクション呼び出しボタンが青の代わりに赤で表示されます。

/**
 * 通知のメールプレゼンテーションを取得
 *
 * @param  mixed  $notifiable
 * @return \Illuminate\Notifications\Message
 */
public function toMail($notifiable)
{
    return (new MailMessage)
                ->error()
                ->subject('Notification Subject')
                ->line('...');
}

データベース通知

事前要件

database通知チャンネルは、通知情報をデータベーステーブルへ保存します。このテーブルは通知タイプのような情報と同時に、通知を説明するカスタムJSONデータを含みます。

アプリケーションのユーザインターフェイスで通知を表示するために、テーブルをクエリすることができます。しかし、その前に通知を保存するデータベーステーブルを作成する必要があります。実際のテーブルスキーマのマイグレーションを生成するために、notifications:tableを使用してください。

php artisan notifications:table

php artisan migrate

データベース通知のフォーマット

通知でデータベーステーブルへの保存をサポートする場合、通知クラスにtoDatabasetoArrayメソッドを定義する必要があります。このメソッドは$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 Vs. toArray

toArrayメソッドは、JavaScriptクライアントへどのデータをブロードキャストするかを決めるために、broadcastチャンネルでも使用されます。databasebroadcastチャンネルで、別々の配列プレゼンテーションを持ちたい場合は、toArrayメソッドの代わりに、toDatabaseメソッドを定義してください。

通知へのアクセス

通知をデータベースへ保存したら、通知エンティティから便利にアクセスできる方法が必要になります。LaravelのデフォルトApp\Userモデルに含まれている、Illuminate\Notifications\Notifiableトレイトは、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リクエストを作成します。

Readとしての通知作成

通常、ユーザが閲覧したときに、その通知を「既読」とマークするでしょう。Illuminate\Notifications\Notifiableトレイトは、通知のデータベースレコード上にある、read_atカラムを更新するmarkAsReadメソッドを提供しています。

$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();

ブロードキャスト通知

事前要件

ブロードキャスト通知の前に、Laravelのイベントブロードキャストサービスを設定し、慣れておく必要があります。イベントブロードキャストは、JavaScriptクライアント側で、サーバサイドで発行されたLaravelイベントに対処する方法を提供しています。

ブロードキャスト通知のフォーマット

broadcastチャンネルは、リアルタイムでJavaScriptクライアントが通知を補足できるようにする、Laravelのイベントブロードキャストサービスを用い、通知をブロードキャストします。通知でブロードキャストをサポートする場合、通知クラスでtoBroadcasttoArrayメソッドを定義する必要があります。このメソッドは$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チャンネルによっても使用されます。databasebroadcastチャンネルで、それぞれ異なった配列プレゼンテーションを持ちたい場合は、toArrayメソッドの代わりにtoBroadcastメソッドを定義してください。

通知のリッスン

プライベートチャンネルにブロードキャストされる通知は、{notifiable}.{id}命名規則に従いフォーマットされます。ですから、IDが1App\Userインスタンスを通知で送る場合、App.User.1プライベートチャンネルへブロードキャストされます。Laravel Echoを使用していれば、notificationヘルパメソッドを使い、チャンネルへの通知を簡単にリッスンできます。

Echo.private('App.User.' + userId)
    .notification((notification) => {
        console.log(notification.type);
    });

SMS通知

事前要件

LaravelのSMS通知送信は、Nexmoを使用します。Nexmoにより通知を送れるようにする前に、nexmo/client Composerパッケージをインストールし、config/services.php設定ファイルへ設定オプションをいくつか追加する必要があります。参考例として、以下の設定をコピーしてください。

'nexmo' => [
    'key' => env('NEXMO_KEY'),
    'secret' => env('NEXMO_SECRET'),
    'sms_from' => '15556666666',
],

sms_fromオプションはSMSメッセージを送る電話番号です。アプリケーションの電話番号は、Nexmoコントロールパネルで作成してください。

SMS通知のフォーマット

SMSとしての通知をサポートするには、通知クラスにtoNexmoメソッドを定義する必要があります。このメソッドは$notifiableエンティティを受け取り、Illuminate\Notifications\Messages\NexmoMessageインスタンスを返す必要があります。

/**
 * 通知のNexmo/SMSプレゼンテーションを取得する
 *
 * @param  mixed  $notifiable
 * @return NexmoMessage
 */
public function toNexmo($notifiable)
{
    return (new NexmoMessage)
                ->content('Your SMS message content');
}

"from"電話番号のカスタマイズ

config/services.phpファイルで指定した電話番号とは異なる番号から、通知を送りたい場合は、NexmoMessageインスタンスのfromメソッドを使用します。

/**
 * 通知のNexmo/SMSプレゼンテーションを取得する
 *
 * @param  mixed  $notifiable
 * @return NexmoMessage
 */
public function toNexmo($notifiable)
{
    return (new NexmoMessage)
                ->content('Your SMS message content')
                ->from('15554443333');
}

SMS通知のルート指定

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;
    }
}

Slack通知

事前要件

Slackを通じ通知を送る場合、Guzzle HTTPライブラリをComposerでインストールする必要があります。

composer require guzzlehttp/guzzle

さらに、Slackチームの"Incoming Webhook"インテグレーションを設定する必要もあります。このインテグレーションは、Slack通知のルートを行う時に使用するURLを提供します。

Slack通知のフォーマット

通知がSlackメッセージとしての送信をサポートする場合、通知クラスにtoSlackメソッドを定義する必要があります。このメソッドは$notifiableエンティティを受け取り、Illuminate\Notifications\Messages\SlackMessageインスタンスを返す必要があります。Slackメッセージはテキストと同時に、追加テキストのフォーマットか、フィールドの配列を「添付」として含みます。基本的なtoSlackの例を見てください。

/**
 * 通知のSlackプレゼンテーションを取得
 *
 * @param  mixed  $notifiable
 * @return SlackMessage
 */
public function toSlack($notifiable)
{
    return (new SlackMessage)
                ->content('One of your invoices has been paid!');
}

この例では、Slackへ一行のテキストを送っており、以下のようなメッセージが生成されます。

Slack添付

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メッセージを生成します。

添付ではさらに、ユーザに対し表示すべきデータの配列を指定することもできます。指定したデータは簡単に読めるように、テーブルスタイルの形式で表示されます。

/**
 * 通知の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メッセージを作成します。

送信者と受信者のカスタマイズ

fromtoメソッドを使い、送信者と受信者のカスタマイズができます。fromメソッドはユーザ名と絵文字識別子を受け付け、toメソッドはチャンネルかユーザ名を受け取ります。

/**
 * 通知のSlackプレゼンテーションを取得
 *
 * @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通知をルートするには、通知可能エンティティのrouteNotificationForSlackメソッドを定義します。これは通知が配送されるべきWebhook URLを返す必要があります。Webhook 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;
    }
}

通知イベント

通知が送信されると、Illuminate\Notifications\Events\NotificationSentイベントが、通知システムにより発行されます。これには「通知可能」エンティティと通知インスンタンス自身が含まれます。このイベントのリスナは、EventServiceProviderで登録します。

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Notifications\Events\NotificationSent' => [
        'App\Listeners\LogNotification',
    ],
];

Tip!! EventServiceProviderでリスナを登録した後に、event:generate Artisanコマンドを使うと、リスナークラスが素早く生成できます。

イベントリスナーの中で、通知受取人や通知自身について調べるために、そのイベントのnotifiablenotificationchannelプロパティにアクセスできます。

/**
 * Handle the event.
 *
 * @param  NotificationSent  $event
 * @return void
 */
public function handle(NotificationSent $event)
{
    // $event->channel
    // $event->notifiable
    // $event->notification
}

カスタムチャンネル

Laravelはいくつかの通知チャンネルを用意していますが、他のチャンネルを使用し通知を配信するために、独自のドライバーを書くこともあるでしょう。Laravelでは、これも簡単です。手始めに、sendメソッドを含むクラスを定義しましょう。このメソッドは$notifiable$notificationの、2引数を受け取ります。

<?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)
    {
        // ...
    }
}

ドキュメント章別ページ

開発環境
ビューとテンプレート
Artisanコンソール
公式パッケージ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

バージョン

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる