RitoLabo

LaravelでSlack通知を実装する~ソーシャルではなく開発者/管理者としてのSlack通知~

  • 公開:
  • カテゴリ: PHP Laravel
  • タグ: PHP,Laravel,5.5,5.4,5.3,Notification,Command,5.6,Repository,Slack

LaravelではモデルベースでのSlack通知は色々と情報がありますが、単純なSlack通知ってなかなか方法が出回っていなかったりします。

これは、ユーザに対しての通知としてSlackへの送信を行う事を基本思想として提供されている為、公式リファレンスでもそういった形での解説になっている部分があります。

しかし開発者からしてみると、単純にアラートとしてSlack通知を活用したりなどの用途で使用したい場合も結構あります。

そこで今回は、シンプルなSlack通知を実装していきます。

アジェンダ
  1. 開発環境
  2. Slack Web API
  3. API情報
  4. Guzzle HTTPライブラリ
  5. Notificationクラス生成
  6. Notificationクラス実装
  7. routeNotificationForSlack()
  8. Slack通知実行

開発環境

今回の開発環境に関しては以下の通りです。

  • Linux CentOS 7
  • Apache 2.4
  • PHP 7.2/7.1
  • composer 1.6.3
  • Laravel

Laravelのバージョンに関しては5.6/5.5/5.4/5.3にて動作確認済みです。

今回はライブラリのインストールも行うので、composerが必要です。

Laravelのルートディレクトリを「laravel/」とします。

Slack Web API

Slack(スラック)とは、言わずと知れたビジネスチャットアプリです。今回はここに通知を送る機能を構築しますが、それには「Slack Web API」を使います。

詳細は割愛しますが、今回はWebhook URLがあれば一定の通知機能は実装できるので、アプリまで作成しなくても、着信Webフックを1つ用意すればOKです。必要な情報を埋めて作成した後、「Webhook URL」のみをメモしておいてください。

着信Webフックを作成するのは、以下のURLから出来ます。
https://YOUR-WORKSPACE-NAME.slack.com/apps/manage/custom-integrations
サブドメイン部を自身のワークスペース名にしてアクセスしてください。

作成が済んだら、Laravel側の実装に進みます。

API情報

まずはSlack Web APIの情報をENVファイルに記述しておきます。

laravel/.env
SLACK_CHANNEL=#ritolabo-notif
SLACK_NAME=RitoLabo
SLACK_ICON=https://yuor-domain.com/icon.png
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/KBE72OW/GYWL3J2OM5/KAt29GBWkFYWn3DPAQ

最低限必要な情報は「Webhook URL」と「チャンネル」です。その他は適宜追加してください。今回は、APP名とアイコン画像を設定しておきます。

Guzzle HTTPライブラリ

Slack通知にはGuzzle HTTPライブラリが必要なので、まずはcomposerでインストールします。Laravelルートディレクトリへ移動し、以下のcomposerコマンドを叩きます。

# Laravelルートディレクトリへ移動
cd /path/to/laravel

# guzzlehttp/guzzleのインストール
composer require guzzlehttp/guzzle

# 実行結果
[demo@localhost laravel]$ composer require guzzlehttp/guzzle
Using version
^6.3 for guzzlehttp/guzzle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)

Package operations: 4 installs, 0 updates, 0 removals
- Installing
guzzlehttp/promises (v1.3.1): Loading from cache
- Installing
psr/http-message (1.0.1): Loading from cache
- Installing
guzzlehttp/psr7 (1.4.2): Loading from cache
- Installing
guzzlehttp/guzzle (6.3.3): Loading from cache
Writing lock file
Generating optimized autoload files

> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: fideloper/proxy
Discovered Package: laravel/dusk
Discovered Package: laravel/tinker
Discovered Package: nunomaduro/collision
Package manifest generated successfully.

Notificationクラス生成

Notificationクラスを作成します。Laravelルートディレクトリへ移動し、以下のartisanコマンドを叩きます。

# Laravelルートディレクトリへ移動
cd /path/to/laravel

# notificationクラスの生成
php artisan make:notification Slack

# 実行結果
[demo@localhost laravel]$ php artisan make:notification Slack
Notification created successfully.

laravel/app/Notifications 配下に Slack.php が生成されます。

laravel
├─ app
│   ├─ Notifications
│   │   └─
Slack.php
laravel/app/Notifications/Slack.php
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;

class Slack extends Notification
{
use Queueable;

/**
* Create a new notification instance.
*
* @return void
*/
public function __construct()
{
//
}

/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}

/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('Thank you for using our application!');
}

/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

Notificationクラス実装

Notificationsクラスを実装します。以下のようになります。

laravel/app/Notifications/Slack.php
<?php

namespace App\Notifications;

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 $content;
protected $channel;
protected $name;
protected $icon;

/**
* Create a new notification instance.
*
* @return void
*/
public function __construct($message)
{
$this->channel = env('SLACK_CHANNEL');
$this->name = env('SLACK_NAME');
$this->icon = env('SLACK_ICON');
$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)
->image($this->icon)
->to($this->channel)
->content($this->content);
}
}

生成時から追加・変更した部分を以下に記します。

use Illuminate\Notifications\Messages\SlackMessage;

SlackMessageクラスをuseしています。

protected $content;
protected $channel;
protected $name;
protected $icon;

public function __construct($message)
{
$this->channel = env('SLACK_CHANNEL');
$this->name = env('SLACK_NAME');
$this->icon = env('SLACK_ICON');
$this->content = $message;
}

メンバ変数を設定し、それぞれにコンストラクタで設定情報を代入しています。

public function toSlack($notifiable)
{
return (new SlackMessage)
->from($this->name)
->image($this->icon)
->to($this->channel)
->content($this->content);
}

toSlack()メソッドを定義しています。from()にはAPP名、image()にはアイコン、to()にはチャンネル、そしてcontent()には通知するメッセージを渡します。

toMail()メソッドは今回は不要なので削除しています。

routeNotificationForSlack()

次に、Slackチャンネルに対する通知をルートするrouteNotificationForSlack()メソッドを定義するクラスを作成します。

これはRepositoryパターンで実装します。以下の構成でディレクトリとファイルを作成してください。

laravel
├─ app
│   ├─
Repositories
│   │   └─
Slack
│   │   ├─
SlackRepositoryInterface.php
│   │   └─
SlackRepository.php

それぞれを実装していきます。

laravel/app/Repositories/Slack/SlackRepositoryInterface.php
<?php
namespace App\Repositories\Slack;

interface SlackRepositoryInterface
{
public function routeNotificationForSlack();
}
laravel/app/Repositories/Slack/SlackRepository.php
<?php
namespace App\Repositories\Slack;

use Illuminate\Notifications\Notifiable;

class SlackRepository implements SlackRepositoryInterface
{
use Notifiable;

protected $slack;

public function routeNotificationForSlack()
{
return env('SLACK_WEBHOOK_URL');
}
}

ここで定義しているSlackRepositoryクラスは、Webhook URLを返すクラスになります。

LaravelでのRepositoryパターン(依存性注入)

Slack通知実行

これでSlackで通知を行う仕組みが全て構築出来ました。これらを使うと、Laravelでのどこのクラスからでも通知を行う事が出来ます。

まずは、自作のArtisanコマンドから送信を行います。以下コマンドを叩いてCommandクラスを生成します。

# Laravelルートディレクトリへ移動
cd /path/to/laravel

# Commandクラスの生成
php artisan make:command SendSlackCommand

# 実行結果
[demo@localhost laravel]$ php artisan make:command SendSlackCommand
Console command created successfully.

laravel/app/Console/Commands 配下に SendSlackNotification.php が生成されます。

laravel
├─ app
│   ├─ Commands
│   │   └─
SendSlackCommand.php

実装は以下になります。

laravel/app/Console/Commands/SendSlackNotification.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

use App\Notifications\Slack;
use App\Repositories\Slack\SlackRepositoryInterface AS SlackPepo;

class SendSlackCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'slack:send {message}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Send Slack Notification';

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return mixed
*/
public function handle(SlackPepo $slackHook)
{
$slackHook->notify(new Slack($this->argument('message')));
$this->line('Send Completed.');
}

}

これでコマンドから送信が可能になります。コマンドヘルプを表示させると、今回作成した自作のArtisanコマンドを確認できます。

# Laravelルートディレクトリへ移動
cd /path/to/laravel

# artisanコマンドのリストを表示する
php artisan

# 実行結果
[demo@localhost laravel]$ php artisan
slack
slack:send Send Slack Notification

そして、このコマンドを送信したいメッセージと共に叩けば、Slackへ通知が送信されます。

# Laravelルートディレクトリへ移動
cd /path/to/laravel

# Slackに通知を送信する
php artisan slack:send 'Hello world!! From Laravel Command'

# 実行結果
[demo@localhost laravel]$ php artisan slack:send 'Hello world!! From Laravel Command'
Send Completed.

コマンドラインからSlackへ送信

こんな感じで、コントローラからの送信も同じようにして行う事ができます。

laravel/app/Http/Controllers/SampleController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Notifications\Slack;
use App\Repositories\Slack\SlackRepositoryInterface AS SlackPepo;

class SampleController extends Controller
{
public function index(SlackPepo $slackHook)
{
$slackHook->notify(new Slack('Slack meets Laravel!!'));
}
}

コントローラからSlackへ送信

まとめ

以上で作業は完了です。コマンドラインなら例えばバッチ処理などの結果や、エラー発生時に通知するにも使えますし、通常通り何かの処理ついでにコントローラから投げるのもありです(キューには入れたいところ)。

案件によってはメール通知という手段もそつなく抑えつつ、いち早く情報を掴む為にSlack通知を行うのもおすすめです。是非試してみてください。