Skip to content
全部文档

面板配置

简介

默认情况下,配置文件位于 app/Providers/Filament/AdminPanelProvider.php。继续阅读以了解 面板 以及每个面板如何拥有 自己的配置文件

认识面板

默认情况下,安装该包后会为你设置好一个面板,位于 /admin。你创建的所有 资源自定义页面仪表盘小部件 都会注册到此面板。

不过,你可以创建任意数量的面板,每个面板都可以拥有自己的资源、页面和小部件。

例如,你可以构建一个面板,让用户在 /app 登录并访问仪表盘,管理员在 /admin 登录并管理应用。/app 面板和 /admin 面板各自拥有资源,因为每组用户的需求不同。Filament 通过支持创建多个面板来实现这一点。

默认 admin 面板

运行 filament:install 时,会在 app/Providers/Filament 中创建新文件 AdminPanelProvider.php。该文件包含 /admin 面板的配置。

本文档提到「配置」时,指的就是需要编辑的这个文件。它允许你完全自定义应用。

创建新面板

若要创建新面板,可以使用 make:filament-panel 命令,并传入新面板的唯一名称:

bash
php artisan make:filament-panel app

此命令会创建一个名为「app」的新面板。配置文件会创建在 app/Providers/Filament/AppPanelProvider.php。你可以在 /app 访问该面板,也可以 自定义路径

由于此配置文件同时也是 Laravel 服务提供者,需要在 bootstrap/providers.php(Laravel 11 及以上的应用结构)或 config/app.php(Laravel 10 及以下的应用结构)中注册。Filament 会尝试替你完成注册,但若访问面板时报错,则该过程可能失败了。

更改路径

在面板配置文件中,可以使用 path() 方法更改应用的访问路径:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->path('app');
}

若希望应用无需任何前缀即可访问,可以将其设为空字符串:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->path('');
}

请确保 routes/web.php 尚未定义 '''/' 路由,否则它们会优先生效。

渲染钩子

渲染钩子 允许你在框架视图的各个位置渲染 Blade 内容。你可以在服务提供者或中间件中 注册全局渲染钩子,也可以注册仅针对某个面板的渲染钩子。为此,可以在面板配置对象上使用 renderHook() 方法。下面是一个将 wire-elements/modal 与 Filament 集成的示例:

php
use Filament\Panel;
use Filament\View\PanelsRenderHook;
use Illuminate\Support\Facades\Blade;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->renderHook(
            PanelsRenderHook::BODY_START,
            fn (): string => Blade::render('@livewire(\'livewire-ui-modal\')'),
        );
}

可用渲染钩子的完整列表见 此处

设置域名

默认情况下,Filament 会响应来自所有域名的请求。若要将其限定到特定域名,可以使用 domain() 方法,类似于 Laravel 中的 Route::domain()

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->domain('admin.example.com');
}

自定义最大内容宽度

默认情况下,Filament 会限制页面内容宽度,以免在大屏幕上过宽。若要更改,可以使用 maxContentWidth() 方法。选项对应 Tailwind 的 max-width 比例。可选值为 ExtraSmallSmallMediumLargeExtraLargeTwoExtraLargeThreeExtraLargeFourExtraLargeFiveExtraLargeSixExtraLargeSevenExtraLargeFullMinContentMaxContentFitContentProseScreenSmallScreenMediumScreenLargeScreenExtraLargeScreenTwoExtraLarge。默认为 SevenExtraLarge

php
use Filament\Panel;
use Filament\Support\Enums\Width;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->maxContentWidth(Width::Full);
}
内容宽度为 Full 的面板内容宽度为 Full 的面板

若要为 SimplePage 类型的页面(如登录和注册页)设置最大内容宽度,可以使用 simplePageMaxContentWidth() 方法。默认为 Large

php
use Filament\Panel;
use Filament\Support\Enums\Width;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->simplePageMaxContentWidth(Width::Small);
}
最大内容宽度为 Small 的登录页最大内容宽度为 Small 的登录页

设置默认子导航位置

子导航默认渲染在每个页面的起始位置。可以按页面、资源和集群自定义,也可以使用 subNavigationPosition() 方法一次性为整个面板自定义。取值可以是 SubNavigationPosition::StartSubNavigationPosition::End,或 SubNavigationPosition::Top(将子导航渲染为标签页):

php
use Filament\Pages\Enums\SubNavigationPosition;
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->subNavigationPosition(SubNavigationPosition::End);
}

生命周期钩子

钩子可用于在面板生命周期中执行代码。bootUsing() 会在该面板内的每次请求时运行。若有多个面板,仅会运行当前面板的 bootUsing()。该函数从中间件中运行,时机是在所有服务提供者启动之后:

php
use Filament\Panel;

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

SPA 模式

SPA 模式利用 Livewire 的 wire:navigate 功能,让服务端渲染的面板感觉像单页应用:页面切换延迟更小,较长请求会显示加载条。要在面板上启用 SPA 模式,可以使用 spa() 方法:

php
use Filament\Panel;

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

为特定 URL 禁用 SPA 导航

默认情况下,启用 SPA 模式后,与当前请求位于同一域名的任何 URL 都会使用 Livewire 的 wire:navigate 进行导航。若要为特定 URL 禁用此行为,可以使用 spaUrlExceptions() 方法:

php
use App\Filament\Resources\Posts\PostResource;
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->spa()
        ->spaUrlExceptions(fn (): array => [
            url('/admin'),
            PostResource::getUrl(),
        ]);
}

INFO

本例中,我们在资源上使用 getUrl() 获取资源索引页的 URL。此功能需要面板已经注册,而配置发生在请求生命周期中过早的阶段,无法做到这一点。你可以使用函数返回 URL,它们会在面板注册后再解析。

这些 URL 需要与用户正在导航到的 URL 完全匹配,包括域名和协议。若要用模式匹配多个 URL,可以使用星号(*)作为通配符:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->spa()
        ->spaUrlExceptions([
            '*/admin/posts/*',
        ]);
}

启用 SPA 预取

SPA 预取会在用户悬停链接时自动预取页面,使导航感觉更加灵敏。此功能利用 Livewire 的 wire:navigate.hover 能力

若要启用带预取的 SPA 模式,可以向 spa() 方法传入 hasPrefetching: true 参数:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->spa(hasPrefetching: true);
}

启用预取后,面板内的所有链接都会自动包含 wire:navigate.hover,在用户悬停链接时预取页面内容。这与 URL 例外 无缝配合——从 SPA 模式排除的任何 URL 也会从预取中排除。

INFO

预取仅在启用 SPA 模式时生效。若禁用 SPA 模式,预取也会自动禁用。

WARNING

预取较重的页面会增加带宽占用和服务器负载,尤其是用户快速悬停大量链接时。请谨慎使用此功能,特别是应用中有包含大量数据或复杂查询的页面时。

未保存更改提醒

你可以在用户试图离开页面且未保存更改时发出提醒。这会应用于资源的 创建编辑 页面,以及任何已打开的操作模态框。要启用此功能,可以使用 unsavedChangesAlerts() 方法:

php
use Filament\Panel;

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

禁用了 schema 的操作模态框(例如只读的 ViewAction 模态框)不会触发提醒。你也可以使用 unsavedChangesAlert(false) 方法,为另一个不可能包含未保存更改的操作禁用提醒

启用数据库事务

默认情况下,Filament 不会将操作包裹在数据库事务中,而是让用户在测试确认操作可以安全地包裹在事务中之后自行启用。不过,你可以使用 databaseTransactions() 方法一次性为所有操作启用数据库事务:

php
use Filament\Panel;

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

对于不想包裹在事务中的操作,可以使用 databaseTransaction(false) 方法:

php
CreateAction::make()
    ->databaseTransaction(false)

对于 创建资源编辑资源 等页面,可以在页面类上将 $hasDatabaseTransactions 属性定义为 false

php
use Filament\Resources\Pages\CreateRecord;

class CreatePost extends CreateRecord
{
    protected ?bool $hasDatabaseTransactions = false;

    // ...
}

为特定操作和页面选择加入数据库事务

除了在所有地方启用数据库事务再为特定操作和页面退出之外,你也可以仅为特定操作和页面选择加入数据库事务。

对于操作,可以使用 databaseTransaction() 方法:

php
CreateAction::make()
    ->databaseTransaction()

对于 创建资源编辑资源 等页面,可以在页面类上将 $hasDatabaseTransactions 属性定义为 true

php
use Filament\Resources\Pages\CreateRecord;

class CreatePost extends CreateRecord
{
    protected ?bool $hasDatabaseTransactions = true;

    // ...
}

为面板注册资源

你可以注册仅在特定面板页面中加载、而不会在应用其余部分加载的 资源。为此,将资源数组传给 assets() 方法:

php
use Filament\Panel;
use Filament\Support\Assets\Css;
use Filament\Support\Assets\Js;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->assets([
            Css::make('custom-stylesheet', resource_path('css/custom.css')),
            Js::make('custom-script', resource_path('js/custom.js')),
        ]);
}

在这些 资源 可以使用之前,需要运行 php artisan filament:assets

应用中间件

你可以通过在配置中将中间件类数组传给 middleware() 方法,为所有路由应用额外中间件:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->middleware([
            // ...
        ]);
}

默认情况下,中间件会在页面首次加载时运行,但不会在后续 Livewire AJAX 请求中运行。若要在每次请求都运行中间件,可以将 true 作为第二个参数传给 middleware() 方法,使其持久化:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->middleware([
            // ...
        ], isPersistent: true);
}

为已认证路由应用中间件

你可以通过在配置中将中间件类数组传给 authMiddleware() 方法,为所有已认证路由应用中间件:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->authMiddleware([
            // ...
        ]);
}

默认情况下,中间件会在页面首次加载时运行,但不会在后续 Livewire AJAX 请求中运行。若要在每次请求都运行中间件,可以将 true 作为第二个参数传给 authMiddleware() 方法,使其持久化:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->authMiddleware([
            // ...
        ], isPersistent: true);
}

禁用广播

默认情况下,若已在 已发布的 config/filament.php 配置文件 中设置凭据,Laravel Echo 会为每个面板自动连接。要在某个面板中禁用此自动连接,可以使用 broadcasting(false) 方法:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->broadcasting(false);
}

严格授权模式

默认情况下,Filament 授权用户访问资源时,会先检查该模型是否存在策略,若存在,再检查策略上是否有执行该操作的方法。若策略或策略方法不存在,会授予用户对该资源的访问权限,因为它假定你尚未设置授权,或不需要授权。

若希望在策略或策略方法不存在时由 Filament 抛出异常,可以使用 strictAuthorization() 方法启用严格授权模式:

php
use Filament\Panel;

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

配置错误通知

当 Laravel 的调试模式关闭时,Filament 会用更整洁的闪现通知替换 Livewire 的全屏错误模态框。你可以使用 errorNotifications(false) 方法禁用此行为:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->errorNotifications(false);
}

你可以通过向 registerErrorNotification() 方法的 titlebody 参数传入字符串,自定义错误通知文本:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->registerErrorNotification(
            title: 'An error occurred',
            body: 'Please try again later.',
        );
}

你也可以通过在 statusCode 参数中传入 HTTP 状态码(例如 404),为特定状态码注册错误通知文本:

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->registerErrorNotification(
            title: 'An error occurred',
            body: 'Please try again later.',
        )
        ->registerErrorNotification(
            title: 'Record not found',
            body: 'A record you are looking for does not exist.',
            statusCode: 404,
        );
}

你也可以选择通过将 HTTP 状态码(例如 403)传给 hiddenErrorNotification() 方法来隐藏该状态码的通知。被隐藏的状态码仍会被 Filament 捕获,但不会显示通知。

或者,你可以使用 disabledErrorNotification() 方法,让该状态码回退到 Livewire 的内置错误处理。这在你想接入 Livewire 错误处理系统、为特定状态码自定义错误处理行为,同时为其他情况保留 Filament 错误通知系统时很有用。

php
use Filament\Panel;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->registerErrorNotification(
            title: 'An error occurred',
            body: 'Please try again later.',
        )
        ->hiddenErrorNotification(403)
        ->disabledErrorNotification(503);
}

你也可以通过在页面类上设置 $hasErrorNotifications 属性,为面板中的特定页面启用或禁用错误通知:

php
use Filament\Pages\Dashboard as BaseDashboard;

class Dashboard extends BaseDashboard
{
    protected ?bool $hasErrorNotifications = true;

    // or

    protected ?bool $hasErrorNotifications = false;

    // ...
}

若要运行自定义代码来检查是否应显示错误通知,可以在页面类上使用 hasErrorNotifications() 方法:

php
use Filament\Pages\Dashboard as BaseDashboard;

class Dashboard extends BaseDashboard
{
    public function hasErrorNotifications(): bool
    {
        return FeatureFlag::active();
    }

    // ...
}

你也可以在 setUpErrorNotifications() 方法中调用页面类上的 registerErrorNotification() 方法来注册错误通知文本:

php
use Filament\Pages\Dashboard as BaseDashboard;

class Dashboard extends BaseDashboard
{
    protected function setUpErrorNotifications(): void
    {
        $this->registerErrorNotification(
            title: 'An error occurred',
            body: 'Please try again later.',
        );
    }

    // ...
}

你也可以通过在 statusCode 参数中传入 HTTP 状态码(例如 404),为特定状态码注册错误通知文本:

php
use Filament\Pages\Dashboard as BaseDashboard;

class Dashboard extends BaseDashboard
{
    protected function setUpErrorNotifications(): void
    {
        $this->registerErrorNotification(
            title: 'An error occurred',
            body: 'Please try again later.',
        );

        $this->registerErrorNotification(
            title: 'Record not found',
            body: 'A record you are looking for does not exist.',
            statusCode: 404,
        );
    }

    // ...
}

你也可以选择通过将 HTTP 状态码(例如 403)传给 hiddenErrorNotification() 方法来隐藏该状态码的通知。被隐藏的状态码仍会被 Filament 捕获,但不会显示通知。

或者,你可以使用 disabledErrorNotification() 方法,让该状态码回退到 Livewire 的内置错误处理。这在你想接入 Livewire 错误处理系统、为特定状态码自定义错误处理行为,同时为其他情况保留 Filament 错误通知系统时很有用。

php
use Filament\Pages\Dashboard as BaseDashboard;

class Dashboard extends BaseDashboard
{
    protected function setUpErrorNotifications(): void
    {
        $this->registerErrorNotification(
            title: 'An error occurred',
            body: 'Please try again later.',
        );

        $this->hiddenErrorNotification(403);

        $this->disabledErrorNotification(503);
    }

    // ...
}