#04 FilamentPHP応用

通知とリアルタイム更新——Notificationsシステム

FilamentのNotificationシステム概要

Filamentには画面右下(または右上)にトースト通知を表示する仕組みが内蔵されています。ユーザーのアクション後のフィードバック・エラー通知・処理完了の報告など、あらゆる場面で活用できます。

通知は大きく分けて2種類あります。

種類説明
フラッシュ通知一時的なトースト表示(数秒で消える)
データベース通知DBに保存され、通知センターで確認できる

基本的な通知の送信

use Filament\Notifications\Notification;

Notification::make()
    ->title('保存しました')
    ->success()
    ->send();

->success()の代わりに以下のステータスが使えます。

メソッド用途
->success()正常完了
->warning()注意が必要な情報
->danger()エラー・失敗
->info()参考情報

->body()->icon()->color()->duration() で詳細設定

Notification::make()
    ->title('記事を公開しました')
    ->body('「Filamentの使い方」が公開されました。アクセスは管理画面から確認できます。')
    ->icon('heroicon-o-globe-alt')
    ->color('success')
    ->duration(8000)    // 表示時間(ミリ秒)。falseで消えない
    ->send();

->duration(false)を指定すると手動で閉じるまで表示し続けます。重要なメッセージに使います。

Actionクラス内での通知

アクションのコールバック内で通知を送るのが最も一般的なパターンです。

Action::make('publish')
    ->action(function (Post $record): void {
        try {
            $record->update(['status' => 'published', 'published_at' => now()]);

            Notification::make()
                ->title('公開完了')
                ->body("「{$record->title}」を公開しました。")
                ->success()
                ->send();
        } catch (\Exception $e) {
            Notification::make()
                ->title('公開に失敗しました')
                ->body($e->getMessage())
                ->danger()
                ->send();
        }
    })

データベース通知: ->sendToDatabase($user)

通知をデータベースに保存して、後から確認できるようにします。まずnotificationsテーブルのマイグレーションを実行します。

php artisan make:notifications-table
php artisan migrate

次にUserモデルにNotifiableトレイトが追加されていることを確認してください(Laravelのデフォルトで含まれています)。

Notification::make()
    ->title('新しいコメントが届きました')
    ->body('記事「Filamentの使い方」にコメントが付きました。')
    ->icon('heroicon-o-chat-bubble-left')
    ->actions([
        NotificationAction::make('view')
            ->label('確認する')
            ->url(route('filament.admin.resources.posts.edit', $post)),
    ])
    ->sendToDatabase($user);

フラッシュ通知とデータベース通知を同時に送ることもできます。

Notification::make()
    ->title('承認が必要な記事があります')
    ->warning()
    ->send()                          // フラッシュ通知
    ->sendToDatabase($adminUsers);    // DB保存(Collectionも渡せる)

通知一覧パネル(DatabaseNotifications)

PanelProviderに->databaseNotifications()を有効化すると、ヘッダーのベルアイコンから通知センターが開きます。

// app/Providers/Filament/AdminPanelProvider.php

public function panel(Panel $panel): Panel
{
    return $panel
        ->default()
        ->id('admin')
        ->path('admin')
        ->databaseNotifications()
        ->databaseNotificationsPolling('30s')  // 30秒ごとに自動更新
        // ...
}

通知センターには未読通知数がバッジ表示され、クリックで既読にできます。

->actions([NotificationAction::make()]) で通知にボタンを追加

データベース通知にアクションボタンを追加して、クリックで関連ページへ遷移させることができます。

use Filament\Notifications\Actions\Action as NotificationAction;

Notification::make()
    ->title('注文が承認待ちです')
    ->body('新しい注文 #1234 が承認を待っています。')
    ->warning()
    ->actions([
        NotificationAction::make('approve')
            ->label('承認する')
            ->color('success')
            ->url(route('filament.admin.resources.orders.edit', $order))
            ->markAsRead(),    // クリック時に既読にする

        NotificationAction::make('dismiss')
            ->label('後で確認')
            ->color('gray')
            ->markAsRead(),
    ])
    ->sendToDatabase($admin);

Laravel Echo + Pusherとの連携設定

リアルタイム通知を実現するためにLaravel EchoとPusher(またはSoketi)を設定します。

composer require pusher/pusher-php-server
npm install --save-dev laravel-echo pusher-js

.envに接続情報を追加:

BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-app-key
PUSHER_APP_SECRET=your-app-secret
PUSHER_APP_CLUSTER=ap3

resources/js/bootstrap.jsでEchoを初期化:

import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

window.Pusher = Pusher;
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
    forceTLS: true,
});

ブロードキャスト通知でリアルタイム更新

Laravelの通知クラスでtoBroadcast()メソッドを実装すると、DB保存と同時にリアルタイム配信されます。

// app/Notifications/OrderApprovalNeeded.php

use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\BroadcastMessage;

class OrderApprovalNeeded extends Notification
{
    public function via($notifiable): array
    {
        return ['database', 'broadcast'];
    }

    public function toDatabase($notifiable): array
    {
        return [
            'order_id' => $this->order->id,
            'message' => "注文 #{$this->order->id} が承認待ちです",
        ];
    }

    public function toBroadcast($notifiable): BroadcastMessage
    {
        return new BroadcastMessage([
            'order_id' => $this->order->id,
            'message' => "注文 #{$this->order->id} が承認待ちです",
        ]);
    }
}

Filamentのパネルに->databaseNotifications()が設定されていれば、ブロードキャスト通知が届くたびに通知センターのバッジが自動更新されます。

ポーリングによる自動更新

WebSocketを使わない場合はポーリング(定期的なサーバーリクエスト)で代替できます。

->databaseNotificationsPolling('15s')   // 15秒ごとにポーリング

ポーリング間隔の書式はLivewireのポーリング記法と同じで、10s1m500msなどが使えます。サーバー負荷とリアルタイム性のバランスを考慮して設定してください。

通知のカスタムスタイル

パネル全体の通知位置を変更することもできます。

->notificationPosition(NotificationPosition::BottomRight)  // デフォルト
->notificationPosition(NotificationPosition::TopRight)
->notificationPosition(NotificationPosition::BottomLeft)

まとめ

FilamentのNotificationシステムは、フラッシュ通知からリアルタイムDB通知まで一貫したAPIで扱えます。->sendToDatabase()でDB保存、Laravel Echoと組み合わせることでリアルタイム配信が実現します。次のエピソードではCSVインポート・エクスポート機能を解説します。