Skip to content
全部文档

插件开发

简介

Filament 插件的基础是 Laravel 包。通过 Composer 安装到 Filament 项目中,并遵循所有标准做法,例如用 service providers 注册路由、视图与翻译。若你刚接触 Laravel 包开发,以下资源有助于掌握核心概念:

  • [Laravel 文档的 Package Development 一节](https://laravel.com/docs/packages) 是很好的参考指南。
  • [Spatie 的 Package Training 课程](https://spatie.be/products/laravel-package-training) 是逐步讲解流程的优质视频系列。
  • [Spatie 的 Package Tools](https://github.com/spatie/laravel-package-tools) 可用流畅配置对象简化 service provider 类。

Filament 插件建立在 Laravel 包概念之上,让你能为任意 Filament 面板交付与使用可复用功能。可逐个面板添加,也可按面板分别配置。

用插件类配置面板

插件类用于让你的包与面板配置文件交互。它是一个实现 Plugin 接口的简单 PHP 类,需要实现 3 个方法:

  • `getId()` 方法返回该插件在其他插件中的唯一标识符。请确保足够具体,以免与同一项目中可能使用的其他插件冲突。
  • `register()` 方法可使用面板可用的任意[配置](/5.x/panel-configuration)选项,包括注册 [resources](/5.x/resources/overview)、[自定义页面](/5.x/navigation/custom-pages)、[themes](/5.x/styling/overview#creating-a-custom-theme)、[render hooks](/5.x/panel-configuration#render-hooks) 等。
  • `boot()` 方法仅在注册该插件的面板实际使用时运行,由中间件类执行。
php
<?php

namespace DanHarrin\FilamentBlog;

use DanHarrin\FilamentBlog\Pages\Settings;
use DanHarrin\FilamentBlog\Resources\CategoryResource;
use DanHarrin\FilamentBlog\Resources\PostResource;
use Filament\Contracts\Plugin;
use Filament\Panel;

class BlogPlugin implements Plugin
{
    public function getId(): string
    {
        return 'blog';
    }

    public function register(Panel $panel): void
    {
        $panel
            ->resources([
                PostResource::class,
                CategoryResource::class,
            ])
            ->pages([
                Settings::class,
            ]);
    }

    public function boot(Panel $panel): void
    {
        //
    }
}

插件用户可通过实例化插件类,并将其传给配置plugin() 方法,把插件加入面板:

php
use DanHarrin\FilamentBlog\BlogPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugin(new BlogPlugin());
}

流畅地实例化插件类

你可为插件类添加 make() 方法,为用户提供流畅的实例化接口。此外,通过容器(app())实例化插件对象,可在运行时替换为其他实现:

php
use Filament\Contracts\Plugin;

class BlogPlugin implements Plugin
{
    public static function make(): static
    {
        return app(static::class);
    }
    
    // ...
}

现在用户可使用 make() 方法:

php
use DanHarrin\FilamentBlog\BlogPlugin;
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugin(BlogPlugin::make());
}

按面板配置插件

你可为插件类添加其他方法,供用户配置。建议为每个选项同时提供 setter 与 getter:在 setter 中用属性存储偏好,在 getter 中再取出:

php
use DanHarrin\FilamentBlog\Resources\AuthorResource;
use Filament\Contracts\Plugin;
use Filament\Panel;

class BlogPlugin implements Plugin
{
    protected bool $hasAuthorResource = false;
    
    public function authorResource(bool $condition = true): static
    {
        // This is the setter method, where the user's preference is
        // stored in a property on the plugin object.
        $this->hasAuthorResource = $condition;
    
        // The plugin object is returned from the setter method to
        // allow fluent chaining of configuration options.
        return $this;
    }
    
    public function hasAuthorResource(): bool
    {
        // This is the getter method, where the user's preference
        // is retrieved from the plugin property.
        return $this->hasAuthorResource;
    }
    
    public function register(Panel $panel): void
    {
        // Since the `register()` method is executed after the user
        // configures the plugin, you can access any of their
        // preferences inside it.
        if ($this->hasAuthorResource()) {
            // Here, we only register the author resource on the
            // panel if the user has requested it.
            $panel->resources([
                AuthorResource::class,
            ]);
        }
    }
    
    // ...
}

此外,可用插件的唯一 ID 在插件类外部访问其任意配置选项。将 ID 传给 filament() 方法即可:

php
filament('blog')->hasAuthorResource()

访问配置时你可能希望更好的类型安全与 IDE 自动完成。实现方式完全由你决定;一种做法是在插件类上添加静态方法来获取:

php
use Filament\Contracts\Plugin;

class BlogPlugin implements Plugin
{
    public static function get(): static
    {
        return filament(app(static::class)->getId());
    }
    
    // ...
}

现在可用新的静态方法访问插件配置:

php
BlogPlugin::get()->hasAuthorResource()

在插件中分发整个面板

在 Laravel 包中分发整个面板非常容易。用户只需安装你的插件,即可获得应用中一整块预构建功能。

配置面板时,配置类继承 PanelProvider,它是标准的 Laravel service provider。可在包中将其作为 service provider 使用:

php
<?php

namespace DanHarrin\FilamentBlog;

use Filament\Panel;
use Filament\PanelProvider;

class BlogPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->id('blog')
            ->path('blog')
            ->resources([
                // ...
            ])
            ->pages([
                // ...
            ])
            ->widgets([
                // ...
            ])
            ->middleware([
                // ...
            ])
            ->authMiddleware([
                // ...
            ]);
    }
}

然后在包的 composer.json 中将其注册为 service provider:

json
"extra": {
    "laravel": {
        "providers": [
            "DanHarrin\\FilamentBlog\\BlogPanelProvider"
        ]
    }
}