概要
Laravelの通知と例外処理の勉強のために実装してみました。
Notificationに関する記事は数多くあり、公式ドキュメントでも解説されていますが、備忘録としてかんたんな流れを残しておきます。
環境
- Laravel 6.0
- PHP 7.2
事前準備
Guzzleとslack-notification-channelのインストール
$ composer install guzzlehttp/guzzle
$ composer install laravel/slack-notification-channel
SlackのWebhookURLを取得する
今回はenvの値をconfig経由で使用します。
webhookURL取得手順については割愛しますね...
return [
    'name' => env('SLACK_NAME'),
    'channel' => env('SLACK_CHANNEL'),
    'webhook_url' => env('SLACK_WEBHOOK_URL'),
];
通知用クラスの作成
ひとまずslackにメッセージを送信できるように実装します。
初期状態ではメール送信がデフォルトになっているので、slack用に変更してあげます。
<?php
namespace App\Notifications;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
class Slack extends Notification
{
    use Queueable;
    protected $name;
    protected $channnel;
    protected $content;
     
    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($message)
    {
        $this->name = config(slack.name);
        $this->channel = config(slack.channnel);
        $this->content = $message;
    }
    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['slack'];
    }
    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
    /**
     * @param $notifiable
     * @return $this
     */
    public function toSlack($notifiable)
    {
        return (new SlackMessage)
            ->from($this->name)
            ->to($this->channel)
            ->content($this->content);
    }
}
コンストラクタでmessageを受け取り、toSlack()でそのまま送信するシンプルな処理です。
通知を配信するチャンネルをslackにするため、via()の中を'slack'に変更します。
Slack通知用のルートを作成する
<?php
namespace App\Service\Slack;
use Illuminate\Notifications\Notifiable;
use App\Notifications\SlackNotification;
use Exception;
use Illuminate\Notifications\RoutesNotifications;
class SlackNotifiable
{
  use Notifiable;
  protected function routeNotificationForSlack()
  {
    return config('slack.webhook_url');
  }
}
実際にSlack通知をルートするために、routeNotificationForSlack()を定義しWebhookURLを返しています。
Notifiableトレイトを読み込み、notify()で通知を送信できます。
これでSlackにメッセージを送信する準備はOKです!
例外処理に通知を組み込む
Laravelのエラーハンドリングは基本的にapp\Exceptions\Handler.phpが担っています。
ざっくりした流れとしては
- report()で例外をキャッチ
- 親クラスであるIlluminate\Foundation\Exceptions\Handler.phpでrenderレスポンスのために条件分岐
 ログインエラーなのか,バリデーションエラーなのか等々...
- render()でレスポンスを返す。
今回は、例外検知時に通知を送りたいので、report()を編集します。
public function report(Exception $exception)
    {
        $slackHook = new SlackNotifiable();
        $slackHook->notify(new Slack($exception));
        parent::report($exception);
    }
SlackNotifiableのインスタンスを作成し,notify()メソッドを実行することで通知を送っています。
引数にキャッチした例外$exceptionを渡しています。
Slack通知用クラスの修正
最後にApp\Notifications\Slack.phpで例外内容を通知するように修正します。
<?php
namespace App\Notifications;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
class Slack extends Notification
{
    use Queueable;
    protected $name;
    protected $channnel;
    protected $exception;
     
    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct(Exception $e)
    {
        $this->name = config(slack.name);
        $this->channel = config(slack.channnel);
        $this->exception = $e;
    }
    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['slack'];
    }
    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
    /**
     * @param $notifiable
     * @return $this
     */
    public function toSlack($notifiable)
    {
        $exception = $this->exception;
        return (new SlackMessage)
            ->from($this->name)
            ->to($this->channel)
            ->error()
            ->content('エラーを検知しました')
            ->attachment(function ($attachment) use ($exception) {
                $attachment
                    ->title(get_class($exception))
                    ->content($exception->getMessage());
            });
    }
}
コンストラクタでExceptionを受け取るように修正しています。
これでエラー内容をSlackで確認することができるようになりました!

おわりに
最後まで読んでくださってありがとうございました。
至らぬ点など有りましたら、コメントで指摘して頂けるとありがたいです...
Laravelの通知処理を理解するのに良い勉強になりました。
次はキューとか使った非同期処理もやってみたいなぁ。