LaravelからSlackにメッセージを送信する

SlackのWebhook URLを取得する

(1) Incoming Webhookのページを開きます。

(2) メッセージを送信するチャンネルを選択して、「Incoming Webhookインテグレーションの追加」ボタンをクリックします。

(3) Webhook URLをコピーします。

(4)「設定を保存する」ボタンをクリックします。

Laravelの設定

セキュリティのため、.envファイルにWebhook URLを設定します。

この値は公開されるべきではないため、注意して管理してください。

# Slack Webhook URL
SLACK_WEBHOOK_URL=<コピーしたWebhook URLを貼り付ける>
# Slackの投稿者の名前
SLACK_USERNAME=webhookbot
# Slackの投稿者のアイコン
SLACK_ICON_EMOJI=:ghost:

Laravelプロジェクトの config ディレクトリ内に slack.php ファイルを作成し、以下の内容を貼り付けます。

<?php
// config/slack.php
return [
    'webhook_url' => env('SLACK_WEBHOOK_URL'),
    'username' => env('SLACK_USERNAME'),
    'icon_emoji' => env('SLACK_ICON_EMOJI'),
];

Slackにメッセージを送信するクラスを作成する

Slackにメッセージを送信するクラスを作成します。

<?php
declare(strict_types=1);

// app/Services/SlackService.php
namespace App\Services;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;

class SlackService
{
    public static function post(string $message): bool
    {
        $client = new Client();

        $webhookUrl = config('slack.webhook_url');
        $username = config('slack.username');
        $iconEmoji = config('slack.icon_emoji');

        try {
            $client->request(
                'POST',
                $webhookUrl,
                [
                    'headers' => [
                        'Content-Type' => 'application/json',
                    ],
                    'body' => json_encode([
                        'username' => $username,
                        'text' => $message,
                        'icon_emoji' => $iconEmoji,
                    ]),
                ]);
            return true;
        } catch (GuzzleException $e) {
            Log::error('Slack Post Failed: '.$e->getMessage());
            Log::error('Failed message: '.$message);
            Log::error($e->getTraceAsString());
            return false;
        }
    }
}

Slackにメッセージを送信する

SlackServiceを使用して、メッセージを送信します。

例として、コントローラーから以下のように呼び出すことができます。

use App\Services\SlackService;

// コントローラーのメソッド内で
SlackService::post('Hello, Slack!');

Amazon Fireタブレットのウェイクワードを変更する方法

Amazon Fireタブレットで「アレクサ、10分後にアラーム」と呼びかけると、2台のFireタブレットが同時に応答してしまうことがあります。このような状況を避けるために、ウェイクワード(呼びかけの名前)を変更する方法を紹介します。

変更手順

  1. Fireタブレットで「設定」アプリを開きます。
  2. 一覧から「Alexa」を選択します。
  3. 「ハンズフリーモード」を探し、それを選択します。
  4. 「ハンズフリーモード」をオンにします(もしまだオフになっている場合)。
  5. 「ウェイクワード」のオプションを選択し、希望のウェイクワードを選びます。

現在、ウェイクワードは「Alexa」または「Amazon」のどちらかを選ぶことができます。
これにより、同じ環境内に複数のFireタブレットがある場合でも、特定のデバイスだけに反応させることが可能です。

PHP8で「PDOException: There is no active transaction」エラー

PHP8を使用している際に「PDOException: There is no active transaction」というエラーに遭遇した場合の対処法について解説します。

環境

  • PHP 8.0
  • MySQL 8.0

問題

「PDOException: There is no active transaction」というエラーが発生しました。

調査を進めていくと、トランザクションの中でテーブルをtruncateする際にこのエラーが発生していることがわかりました。

以下に、問題を再現するための最小限のコードを示します。

public function testTruncate(): void
{
    DB::transaction(function () {
        MyModel::query()->truncate();
    });
}

原因

このエラーの原因は、PHP 8.0でのPDO MySQLの扱いの変更にあります。
PHP 8.0では、トランザクションの状態がより厳格に管理されています。
これはPHPの公式マニュアルで確認できます。

また、MySQLのTRUNCATE TABLEステートメントは実行されると暗黙のコミットが発生します。
この点についてはMySQL 8.0 リファレンスマニュアルに詳細が記載されています。

truncateを実行すると、暗黙のコミットによりトランザクションが終了してしまいます。
その結果、トランザクションが存在しなくなり、「PDOException: There is no active transaction」というエラーが発生するのです。

LaravelでCSVファイルをアップロードする処理をテストする

概要

Laravelを使用してCSVファイルをアップロードする処理のテスト方法を説明します。

UploadedFile::fake()->createWithContent()を使うと、簡単にテスト用のCSVファイルを作成できます。

解説

createWithContent() メソッドを用いて、テスト用のCSVファイルを作成します。
このメソッドの第一引数にはファイル名を、第二引数にはファイルの内容を指定します。

以下の例では、id, name, created_at, updated_at の4つのカラムを持つCSVファイルを作成しています。

$content = <<<EOF
id,name,created_at,updated_at
1,北海道,2020-01-01 00:00:00,2020-01-01 00:00:00
2,青森県,2020-01-01 00:00:00,2020-01-01 00:00:00
EOF;
$file = UploadedFile::fake()->createWithContent('test.csv', $content);

次に、作成したCSVファイルをアップロードし、そのプロセスをテストします。

以下の例では、POSTリクエストを/uploadエンドポイントに送信し、レスポンスのステータスコードが200であることを確認しています。

$response = $this->json('POST', '/upload', [ 
    'csv_file' => $file,
]);
$response->assertStatus(200);

この方法を利用することで、LaravelアプリケーションにおけるCSVファイルのアップロード処理のテストが容易になります。

環境

  • PHP 8.0.6
  • Laravel バージョン6.20.27