menu-icon

Laravel 6で問い合わせフォームを作ってみる2(Slack送信部分)

前回、フォームの基本的な部分を実装しました。2回目の今回は、"通知"を使用して、問い合わせ内容をSlackに送信する部分を作っていきます。

前回の記事はこちら

準備

Incoming Webhook URLの取得

送信にWebhook URL が必要です。Slack App の Incoming Webhook で取得しておきます。

パッケージインストール

Composerで必要なパッケージをインストールします。

$ composer require laravel/slack-notification-channel

実装

環境変数とコンフィグ

まず.envにWebhook URLを追加します(サンプルのURLは適当です)。

.env
SLACK_INQUIRY_CHANNEL=https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxx/xxxxxxx

つぎにconfig/services.php に以下を追加し、アプリケーションがconfig経由でWebhook URLを読み込めるようにします。

config/services.php
    'slack' => [
        'inquiry' => env('SLACK_INQUIRY_CHANNEL'),
    ],

これで config('services.slack.inquiry') でWebhook URL を読めるようになります。

"通知"を送信するモデルクラス

"通知"を送信するため、Illuminate\Notifications\NotifiableNotifiableトレイトをuseしたクラスを用意します。今回は単純にフォームデータを保持するだけのモデルクラス App\Models\Inquiryを用意しました。

app/Models/Inquiry.php
<?php

namespace App\Models;

use Illuminate\Notifications\Notifiable;

class Inquiry
{
    use Notifiable;

    private string $name;
    private string $email;
    private string $message;

    /**
     * コンストラクタ
     *
     * @param array $attributes
     */
    public function __construct(array $attributes)
    {
        foreach ($attributes as $key => $value) {
            $this->$key = $value;
        }
    }

    /**
     * Slackチャンネルに対する通知をルートする
     *
     * @param  \Illuminate\Notifications\Notification  $notification
     * @return string
     */
    public function routeNotificationForSlack($notification): string
    {
        return config('services.slack.inquiry');
    }

    /**
     * @param string $name
     * @return mixed
     */
    public function __get(string $name)
    {
        if (!property_exists($this, $name)) {
            throw new \Exception("Not found '${name}'.");
        }

        return $this->$name;
    }
}

Slack通知を送信するために、routeNotificationForSlack メソッドでWebhook URLを指定する必要があります。ここで先程のコンフィグを使用しています。

Notification クラス

ArtisanでNotificationを生成します。

$ php artisan make:notification Inquired

app/Notifications/Inquired.php が生成されますので、以下のように編集します。

app/Notifications/Inquired.php
<?php

namespace App\Notifications;

use App\Models\Inquiry;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;

class Inquired extends Notification
{
    use Queueable;

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

    /**
     * 通知のSlackプレゼンテーションを取得
     *
     * @param  Inquiry  $inquiry
     * @return SlackMessage
     */
    public function toSlack(Inquiry $inquiry)
    {
        return (new SlackMessage)
                ->success()
                ->content(sprintf("%s<%s>さんから問い合わせがありました。", $inquiry->name, $inquiry->email))
                ->attachment(function ($attachment) use ($inquiry) {
                    $attachment->content($inquiry->message);
                });
    }
}

viaメソッドで通知を送信するチャンネルを配列で指定します。今回はslackのみです。toSlackメソッドでSlackへ送信する内容を指定します。

コントローラ

InquiryControllerfinishメソッドを修正します。フォームデータからモデルを生成し、Slackへ送信するようにしています。

app/Http/Controllers/InquiryController.php
    public function finish(Request $request)
    {
        if (!$request->session()->has(self::FORM_DATA_KEY)) {
            return redirect()->route('inquiry');
        }

        $form_data = $request->session()->pull(self::FORM_DATA_KEY);
        $inquiry = new Inquiry($form_data);
        $inquiry->notify(new Inquired);

        return view('inquiry.finish');
    }

実行結果

フォームに入力して送信します。

Slackのチャンネルに投稿されたらOKです!

これで問い合わせフォームとして機能するようになりました。次回はreCAPTCHAを使用してBot対策を行います。