LoginSignup
12
13

More than 3 years have passed since last update.

LaravelでFacadeを作ってSlackに通知してみた(Laravel6.xバージョン)

Last updated at Posted at 2020-07-29

概要

前回の記事から約1年経って、Laravelのバージョンも上がったし、私の知識も少しだけ増えたので書き直してみました。

環境

Laravel:6.18.31
PHP:7.4.6

SlackのWebhook URLを取得

SlackにメッセージをPOSTするためのWebhook URLを取得します。

Incoming Webhook を Slack に追加

アプリから取得する場合は、ワークスペースの「App」メニューから検索欄に“Incoming Webhook”と入力して検索してください。
ブラウザで取得する場合は、以下のURLにアクセスしてください。

https://slack.com/apps/A0F7XDUAZ--incoming-webhook-

  • Slack に追加 ボタンをクリック
  • 通知するチャンネルを選択し、Incoming Webhook インテグレーションの追加 ボタンをクリック
  • Webhook URLをコピーする

通知先のチャネルや投稿されるときの名前等は設定画面で登録しておくことができますが、通知するときに指定することもできます。

Incoming Webhook.png

取得したURLは.envファイルに記載しておきます。

.env
SLACK_URL=https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/xxxxxXXxxXxXXxxXXXXXxx

また、Slack 通知用の設定ファイルも用意しておきましょう。

app/config/slack.php
<?php

return [
    // Webhook URL
    'url' => env('SLACK_URL'),
];

Slack 通知の準備

Slack 通知については公式ドキュメントに記載がありますのでそちらも参考にしてください

Slack 通知 - Lavavel 6.x

Slack 通知チャンネルのインストール

composer require laravel/slack-notification-channel

通知クラスの作成

以下のコマンドで Slack 通知クラスを作成します。

php artisan make:notification SlackNotification

app/Notifications/SlackNotification.php というファイルが作成されますので、Slack 通知用に変更していきます。

  • via メソッドが返す配信チャンネルを slack に変更する
  • SlackMessage クラスのインスタンスを返す toSlack メソッドを追加する

SlackMessage クラスの content メソッドでテキストメッセージを送信することができますが、 attachment メソッドで活用することでより詳細な情報をSlackに送ることができます。

app/Notifications/SlackNotification.php
<?php

namespace App\Notifications;

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

class SlackNotification extends Notification
{
    use Queueable;

    /**
     * 通知チャンネル情報
     *
     * @var array
     */
    protected $channel;

    /**
     * 通知メッセージ
     *
     * @var string
     */
    protected $message;

    /**
     * 添付情報
     *
     * @var array
     */
    protected $attachment;

    /**
     * 通知インスタンスの作成
     *
     * @return void
     */
    public function __construct($channel = null, $message = null, $attachment = null)
    {
        $this->channel = $channel;
        $this->message = $message;
        $this->attachment = $attachment;
    }

    /**
     * 通知の配信チャンネルの取得
     *
     * @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($this->channel['username'], $this->channel['icon'])
            ->to($this->channel['channel'])
            ->content($this->message);

        if (!is_null($this->attachment) && is_array($this->attachment)) {
            $message->attachment(function ($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;
    }
}

Slack通知ファサードの作成

設定ファイルにチャンネル情報を追加

app/config/slack.php
<?php

return [
    // Webhook URL
    'url' => env('SLACK_URL'),

    // チャンネル設定
    'default' => 'work',

    'channels' => [
        'work' => [
            'username' => '作業通知',
            'icon' => ':face_with_rolling_eyes:',
            'channel' => 'notice-work',
        ],
        'error' => [
            'username' => 'エラー通知',
            'icon' => ':scream:',
            'channel' => 'notice-error',
        ],
    ],
];

Slack通知サービスの作成

以下の処理を実行するためのサービスを作成します。

  • Notifiableトレイトを利用する
  • 通知先のURLを返す routeNotificationForSlack メソッドを追加する
  • 通知するチャンネルを指定する channel メソッドを追加する
  • send メソッドで Slack 通知クラスのインスタンスを引数として $this->notify() を呼び出す
app/Services/SlackService.php
<?php

namespace App\Services;

use Illuminate\Notifications\Notifiable;
use App\Notifications\SlackNotification;

class SlackService
{
    use Notifiable;

    /**
     * 通知チャンネル情報
     *
     * @var array
     */
    protected $channel = null;

    /**
     * 通知チャンネルを指定
     * 
     * @param array $channnel
     * @return this
     */
    public function channel($channel)
    {
        $this->channel = config('slack.channels.' . $channel);

        return $this;
    }

    /**
     * 通知処理
     *
     * @param string $message
     * @return void
     */
    public function send($message = null)
    {
        if (!isset($this->channel)) {
            $this->channel(config('slack.default'));
        }

        $this->notify(new SlackNotification($this->channel, $message));
    }

    /**
     * Slack通知用URLを指定する
     *
     * @return string
     */
    protected function routeNotificationForSlack()
    {
        return config('slack.url');
    }
}

ファサードクラスの作成

app/Facades/Slack.php
<?php
namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class Slack extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'slack';
    }
}

サービスプロバイダの作成

AppServiceProvider に記載することも可能ですが、常に必要な処理ではないので個別にサービスプロバイダを作成することにします。
サービスプロバイダは以下のコマンドで作成します。

php artisan make:provider SlackServiceProvider

app/Providers/SlackServiceProvider.php というファイルが作成されますので、register メソッドにキーとサービスをバインドする初期を記述します。

app/Providers/SlackServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Services\SlackService;

class SlackServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('slack', SlackService::class);
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

サービスプロバイダとエイリアスを追記する

app/config/app.php

    'providers' => [
        (省略)
        App\Providers\SlackServiceProvider::class,
        (省略)
    ],
    'aliases' => [
        (省略)
        'Slack' => App\Facades\Slack::class,
        (省略)
    ],

通知処理

以下のように記述すればシステム内のどこからでも Slack への通知が可能です。

// メッセージを送信
\Slack::send('Hello World!');

// チャンネルを指定して送信する場合
\Slack::channel('error')->send('Error!!');

おまけ

Tinkerを使えば、画面やコンソールコマンドを用意しなくても動作が確認できます。

php artisan tinker
Psy Shell v0.10.4 (PHP 7.4.6 ― cli) by Justin Hileman
>>> \Slack::send('Hello World!');
=> null
>>> exit
Exit:  Goodbye

詳しくはこちらをご確認ください。

Tinker - Lavavel 6.x

サンプルソース

https://github.com/freeneer/slack-notice-test

12
13
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
13