#08 FilamentPHP応用

プラグインの作り方——再利用可能なFilament拡張

Filamentプラグインとは

FilamentプラグインはPanelに機能を追加する拡張ポイントです。カスタムページ・ウィジェット・フォームコンポーネント・テーブルカラムなどをひとまとめにして、Composerパッケージとして配布・再利用できます。

社内共通の機能をプラグインにまとめたり、OSSとしてコミュニティに公開したりする際に使います。

Plugin インターフェースと register() / boot() メソッド

すべてのFilamentプラグインはFilament\Contracts\Pluginインターフェースを実装します。

namespace App\Filament\Plugins;

use Filament\Contracts\Plugin;
use Filament\Panel;

class ActivityLogPlugin implements Plugin
{
    public function getId(): string
    {
        return 'activity-log';  // ユニークなプラグインID
    }

    public function register(Panel $panel): void
    {
        // パネルにページ・ウィジェット・リソースを追加
        $panel
            ->pages([
                ActivityLogPage::class,
            ])
            ->widgets([
                RecentActivityWidget::class,
            ]);
    }

    public function boot(Panel $panel): void
    {
        // パネル起動後の処理(ルート登録・ミドルウェアなど)
    }
}

FilamentPlugin::make() のファサードパターン

FilamentのプラグインはFluentインターフェースで設定できるmake()ファサードを持つのが慣例です。

namespace App\Filament\Plugins;

use Filament\Contracts\Plugin;
use Filament\Panel;

class ActivityLogPlugin implements Plugin
{
    protected bool $showWidget = true;
    protected int $perPage = 20;
    protected ?string $navigationGroup = null;

    // ファサードパターン
    public static function make(): static
    {
        return app(static::class);
    }

    public static function get(): static
    {
        return filament(app(static::class)->getId());
    }

    // 設定メソッドのチェーン
    public function showWidget(bool $condition = true): static
    {
        $this->showWidget = $condition;
        return $this;
    }

    public function perPage(int $perPage): static
    {
        $this->perPage = $perPage;
        return $this;
    }

    public function navigationGroup(string $group): static
    {
        $this->navigationGroup = $group;
        return $this;
    }

    // ゲッター
    public function getShowWidget(): bool
    {
        return $this->showWidget;
    }

    public function getPerPage(): int
    {
        return $this->perPage;
    }

    // ...
}

プラグインの設定オプション

プラグインに豊富な設定オプションを提供することで、使用者がカスタマイズしやすくなります。

class ActivityLogPlugin implements Plugin
{
    protected array $onlyModels = [];
    protected array $exceptModels = [];
    protected bool $useAuthorizationPolicies = false;

    public function onlyModels(array $models): static
    {
        $this->onlyModels = $models;
        return $this;
    }

    public function exceptModels(array $models): static
    {
        $this->exceptModels = $models;
        return $this;
    }

    public function useAuthorizationPolicies(bool $condition = true): static
    {
        $this->useAuthorizationPolicies = $condition;
        return $this;
    }
}

PanelProviderへの登録

プラグインの使用者はPanelProviderの->plugins()に登録します。

// app/Providers/Filament/AdminPanelProvider.php

public function panel(Panel $panel): Panel
{
    return $panel
        ->default()
        ->id('admin')
        ->plugins([
            ActivityLogPlugin::make()
                ->showWidget(true)
                ->perPage(50)
                ->navigationGroup('監査')
                ->onlyModels([Post::class, User::class]),
        ]);
}

ServiceProviderとの統合

プラグインのServiceProviderでBladeコンポーネント・翻訳ファイル・設定ファイルを登録します。

namespace YourVendor\ActivityLog;

use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;

class ActivityLogServiceProvider extends PackageServiceProvider
{
    public function configurePackage(Package $package): void
    {
        $package
            ->name('laravel-filament-activity-log')
            ->hasConfigFile()
            ->hasViews()
            ->hasMigration('create_activity_log_table')
            ->hasTranslations();
    }

    public function packageBooted(): void
    {
        // Filament関連の登録
        Filament::serving(function () {
            Filament::registerViteTheme('resources/css/filament/admin/theme.css');
        });
    }
}

Composerパッケージとして公開する手順

ディレクトリ構成

packages/
└── activity-log/
    ├── composer.json
    ├── src/
    │   ├── ActivityLogPlugin.php
    │   ├── ActivityLogServiceProvider.php
    │   ├── Filament/
    │   │   ├── Pages/
    │   │   │   └── ActivityLogPage.php
    │   │   └── Widgets/
    │   │       └── RecentActivityWidget.php
    │   └── Models/
    │       └── ActivityLog.php
    ├── resources/
    │   └── views/
    └── database/
        └── migrations/

composer.json

{
    "name": "your-vendor/filament-activity-log",
    "description": "Activity log plugin for Filament",
    "type": "library",
    "require": {
        "php": "^8.2",
        "filament/filament": "^5.0"
    },
    "autoload": {
        "psr-4": {
            "YourVendor\\ActivityLog\\": "src/"
        }
    },
    "extra": {
        "laravel": {
            "providers": [
                "YourVendor\\ActivityLog\\ActivityLogServiceProvider"
            ]
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}

ルートのcomposer.jsonでローカル開発

{
    "repositories": [
        {
            "type": "path",
            "url": "packages/activity-log"
        }
    ],
    "require": {
        "your-vendor/filament-activity-log": "*"
    }
}

プラグインのテスト方法

# パッケージ内でテスト実行
cd packages/activity-log
composer install
./vendor/bin/pest

テスト用のFilamentパネルをオーケストレーションする設定:

// tests/TestCase.php

class TestCase extends Orchestra\Testbench\TestCase
{
    protected function getPackageProviders($app): array
    {
        return [
            FilamentServiceProvider::class,
            ActivityLogServiceProvider::class,
        ];
    }

    protected function defineRoutes($router): void
    {
        // テスト用パネルのルート定義
    }
}

既存の人気プラグイン紹介

FilamentShield

ロールベースアクセス制御(RBAC)を追加します。spatie/laravel-permissionをFilamentと統合し、Resourceごとの権限管理UIが自動生成されます。

composer require bezhansalleh/filament-shield
php artisan shield:generate --all

FilamentSpatieMediaLibrary

spatie/laravel-medialibraryとFilamentを統合し、メディア管理UIを提供します。

composer require filament/spatie-laravel-media-library-plugin

FilamentSpatieTranslatable

多言語コンテンツ管理のプラグインです。

composer require filament/spatie-laravel-translatable-plugin

Filament Excel

ExcelファイルのインポートとエクスポートをFilamentに追加します。

composer require pxlrbt/filament-excel

プラグインのベストプラクティス

  1. 設定値はすべてオプション化する - デフォルト値を適切に設定し、追加設定なしで動作するようにする
  2. 翻訳ファイルを用意する - 日本語・英語など多言語対応
  3. ドキュメントを書く - READMEにインストール手順・使用例を明記
  4. バージョニングを守る - Filamentのバージョンに対応するプラグインバージョンを明示
  5. テストを書く - 主要なユースケースをテストでカバー

まとめ

FilamentプラグインはPluginインターフェースとmake()ファサードパターンで構成されます。register()でパネルにコンポーネントを登録し、Composerパッケージとして配布することで社内外での再利用性が高まります。次のエピソードでは、Filamentリソースのテスト方法を解説します。