プラグインの作り方——再利用可能な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
プラグインのベストプラクティス
- 設定値はすべてオプション化する - デフォルト値を適切に設定し、追加設定なしで動作するようにする
- 翻訳ファイルを用意する - 日本語・英語など多言語対応
- ドキュメントを書く - READMEにインストール手順・使用例を明記
- バージョニングを守る - Filamentのバージョンに対応するプラグインバージョンを明示
- テストを書く - 主要なユースケースをテストでカバー
まとめ
FilamentプラグインはPluginインターフェースとmake()ファサードパターンで構成されます。register()でパネルにコンポーネントを登録し、Composerパッケージとして配布することで社内外での再利用性が高まります。次のエピソードでは、Filamentリソースのテスト方法を解説します。