お知らせ
改善を加えた新記事はこちらになります。
概要
既存のシステムをメンテナンスする上でエラーが発生したときにSlackに通知させるようにしたかったので、そのときの実装内容をメモとして残しておきます。
参考にさせていただいたサンプルではモデルを通知可能(Notifiable)にして通知処理を記述してありましたが、どこからでも呼び出せるように
Facadeを作成して通知する形にしました。
環境
Laravel:5.8
PHP:7.2
SlackのWebhook URLを取得
こちらからSlackと連携するためのWebhook URLを取得します。
https://[通知したいワークスペース名].slack.com/apps/A0F7XDUAZ--incoming-webhook-?next_id=0
取得したURLは.envファイルに記載しておきます。
通知先のチャネルや投稿されるときの名前等は上記の設定画面で設定しておくこともできますが、通知するときに指定することもできるので合わせて.envファイルに記載しておきます。
SLACK_USERNAME=エラー通知
SLACK_ICON=:fire:
SLACK_CHANNEL=notice-error
SLACK_URL=https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/xxxxxXXxxXxXXxxXXXXXxx
Slack通知チャンネルを追加する
Laravel5.7以前はGuzzle HTTPクライアントがあればよかったのですが、5.8以降はSlack通知チャンネルのインストールが必要になります。
> composer require laravel/slack-notification-channel
Notificationクラスを作成する
以下のコマンドでNotificationクラスを作成します。
> php artisan make:notification SlackNotification
app/Notifications/SlackNotification.phpというファイルが作成されますので、Slack通知用に変更していきます。
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Messages\SlackAttachment;
class SlackNotification extends Notification
{
use Queueable;
protected $message;
protected $attachment;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct($message = null, $attachment = null)
{
$this->message = $message;
$this->attachment = $attachment;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['slack'];
}
/**
* Slack通知表現を返します
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\SlackMessage
*/
public function toSlack($notifiable)
{
$message = (new SlackMessage)
->from(env('SLACK_USERNAME'), env('SLACK_ICON'))
->to(env('SLACK_CHANNEL'))
->content($this->message);
if (!is_null($this->attachment) && is_array($this->attachment)) {
$message->attachment(function (SlackAttachment $attachment) {
if (isset($this->attachment['title'])) {
$attachment->title($this->attachment['title']);
}
if (isset($this->attachment['content'])) {
$attachment->content($this->attachment['content']);
}
if (isset($this->attachment['field']) && is_array($this->attachment['field'])) {
foreach($this->attachment['field'] as $k => $v) {
$attachment->field($k, $v);
}
}
});
}
return $message;
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
Slack通知ファサードを作成する
Slack通知処理本体の作成
- Notifiableトレイトを追加する
- 通知先のURLを返すrouteNotificationForSlackメソッドを追加する
- 通知処理の中で$this->notify()を呼び出す
<?php
namespace App\Services\Slack;
use Illuminate\Notifications\Notifiable;
use App\Notifications\SlackNotification;
class SlackService
{
use Notifiable;
public function send($message = null, $attachment = null)
{
$this->notify(new SlackNotification($message, $attachment));
}
protected function routeNotificationForSlack()
{
return env('SLACK_URL');
}
}
ファサードクラスを作成
<?php
namespace App\Services\Slack;
use Illuminate\Support\Facades\Facade;
class SlackFacade extends Facade
{
protected static function getFacadeAccessor()
{
return 'slack';
}
}
サービスプロバイダの作成
以下のコマンドでサービスプロバイダを作成します。
> php artisan make:provider SlackServiceProvider
app/Providers/Slack/SlackServiceProvider.phpというファイルが作成されますので、registerの中にキーとサービスをバインドするための記述を追加します。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class SlackServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->app->bind(
'slack',
'App\Services\Slack\SlackService'
);
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
}
サービスプロバイダとエイリアスを追記する
'providers' => [
(省略)
App\Providers\SlackServiceProvider::class,
(省略)
],
'aliases' => [
(省略)
'Slack' => App\Services\Slack\SlackFacade::class,
(省略)
],
通知処理
以下のように記述すればどこででもSlackへの通知が可能です。
\Slack::send('Hello World!');
参考にさせていただいたサイト
https://readouble.com/laravel/5.8/ja/notifications.html
https://www.ritolab.com/entry/110
https://larapet.hinaloe.net/2017/04/09/slack-notification/
https://qiita.com/nekyo/items/95ede7f8d5c5bd3357fb