📌

LaravelからSlackに通知を送る方法

2024/11/04に公開

まえがき

Laravelで作成中のアプリでなんらかの状態変更や完了通知をSlackに送りたいというケースありますよね。
いくつかそういう記事があって参考にやってみたのですが、非常に苦労した・・・というより実施不可能な壁にぶつかったりしたので、その辺りも含めて解説します。

前提として必要なこと

プログラミングの前にSlackのWebhookURLというものを取得しないといけません。
メールに例えるならこのWebhookURLがメールアドレスみたいなものになります。
なのでこれが分からないと宛先不明でどうやっても届きません。

しかし困ったことにこの取得方法が非常にわかりづらい。
いくつか記事があるのですが、Laravel開発者がslackのワークスペース管理者であることを前提に書いてあるので、手順通りにやっても権限エラーで弾かれて必要なページに入れません。

なので、自分がゲスト参加者とかだとワークスペース管理者からWebhookURLを取得するようお願いするしかありません。

とはいえphp側のソースコードが合ってるか動作確認したいので、その場合自分で無料のワークスペースを新設してそこでテストすることが可能です。

Slack側の設定。WebhookURL取得手順

ワークスペースの管理者でログインします。

まず、このチャンネル一覧から、送りたいチャンネルの名前で右クリックします。

コンテキストメニューから「チャンネル詳細を表示する」をクリック。

インテグレーションタブからアプリを追加するをクリック。

Incomming WebHooksをインストール

Slackに追加をクリック

チャンネルを選択して「Incoming Webhookインテグレーションの追加」をクリック

WebhookURLが表示されるのでコピーしてプログラムで利用する。

Laravelコード

ではここからLaravelでやることです。

Composerで必要なライブラリをインストールする。

slack-notification-channel というライブラリで送信するのでインストールします。

composer require laravel/slack-notification-channel 

Slack通知オブジェクトクラスを作成する。

以下のコマンドを打ちます。

artisan_make.sh notification SlackNotification 

toSlackメソッドにあるSlackMessageがSlackに送る通知メッセージです。
宛先・送り主・内容。

SlackNotification.php
<?php

namespace App\Notifications;

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

class SlackNotification extends Notification
{
    use Queueable;

    protected $message;
    protected $channel;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($message)
    {
        $this->message = $message;
    }

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

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toSlack($notifiable)
    {
        return (new SlackMessage)
            ->from('myname@sample.com') // slackに表示される通知者
            // ->to($this->channel)
            ->content($this->message);
    }

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

SlackServiceクラスをつくる

ここのrouteNotificationForSlackでWebhookURLを指定します。
他の記事では.envに記載してサービスプロバイダーに登録して・・・とかありますが、それは動的に通知先チャンネルを変更するための手法の1つであって、送りたいslackのチャンネルが決まっているのであれば必要ない処理なのであえてベタ書きにしています。

まずは固定チャンネルで通知してみて、通信の確認がとれたら.envでもDBでも好きな方法でWebhookURLを差し替えればいいと思います。

SlackService.php
<?php

namespace App\Services\Common;

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

class SlackService
{
    use Notifiable;

    public function send($message = null)
    {
        $this->notify(new SlackNotification($message));
    }

    public function routeNotificationForSlack()
    {
        // SlackのwebhookURLを指定する。
        return 'https://hooks.slack.com/services/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';
    }
}

コントローラからサービスを呼び出す。

最後にお好きな方法でサービスクラスをインスタン化してsendメソッドを呼びます。
私はコンストラクタインジェクションを使っていますが、動作確認するだけならベタにこんなのでも構いません。
動いてからいい感じにリファクタリングすればいいと思います。

任意のコントローラ.php

public function index(Request $request)
{
    new SlackService $slackService;
    $slackService->send('スラック連係てテスト。');
}

Laravel側はローカル環境のapacheから実行してもちゃんとリモートのSlackへ届きます。

あとがき

お疲れ様でした。
結構ややこしいですが1つ1つ進めていきましょう。

株式会社ONE WEDGE

【Serverlessで世の中をもっと楽しく】 ONE WEDGEはServerlessシステム開発を中核技術としてWeb系システム開発、AWS/GCPを利用した業務システム・サービス開発、PWAを用いたモバイル開発、Alexaスキル開発など、元気と技術力を武器にお客様に真摯に向き合う価値創造企業です。
https://onewedge.co.jp

Discussion