Languages

Version

Theme

资源

代码质量 Tips

使用 Schema 和表格类

由于许多 Filament 方法仅在一个方法中定义应用的 UI 和功能,因此很容易产生庞大的方法和文件。即使你的代码风格简洁一致,这些方法和文件也可能难以阅读。

Filament 尝试通过在生成资源时提供专用的 Schema 和表格类来缓解部分问题。这些类都有一个 configure() 方法,该方法接受 $schema$table 作为参数。然后,你可以从任何想要定义 Schema 或表格的地方调用该 configure() 方法。

例如,如果你有以下 app/Filament/Resources/Customers/Schemas/CustomerForm.php 文件:

namespace App\Filament\Resources\Customers\Schemas;

use Filament\Forms\Components\TextInput;
use Filament\Schemas\Schema;

class CustomerForm
{
    public static function configure(Schema $schema): Schema
    {
        return $schema
            ->components([
                TextInput::make('name'),
                // ...
            ]);
    }
}

你可以在资源的 form() 方法中使用它:

use App\Filament\Resources\Customers\Schemas\CustomerForm;
use Filament\Schemas\Schema;

public static function form(Schema $schema): Schema
{
    return CustomerForm::configure($schema);
}

你页可以对 table() 执行相同的操作:

use App\Filament\Resources\Customers\Schemas\CustomersTable;
use Filament\Tables\Table;

public static function table(Table $table): Table
{
    return CustomersTable::configure($table);
}

或者 infolist()

use App\Filament\Resources\Customers\Schemas\CustomerInfolist;
use Filament\Schemas\Schema;

public static function infolist(Schema $schema): Schema
{
    return CustomerInfolist::configure($schema);
}

这些模式和表类默认没有父类或接口。如果 Filament 强制 configure() 方法使用方法签名,你将无法将自己的配置变量传递给该方法。如果你希望在多个地方重用同一个类,但需要进行一些细微的调整,那么这种方法就非常有用。

使用组件类

即使你使用 Schema 和表类将架构和表定义保存在各自的文件中,最终仍然可能需要一个非常长的 configure() 方法。如果你在 Schema 或表格中使用了大量组件,或者这些组件需要进行大量配置,则尤其如此。

你可以通过为每个组件创建专用类来缓解这种情况。例如,如果你有一个需要大量配置的 TextInput 组件,你可以为其创建一个专用类:

namespace App\Filament\Resources\Customers\Schemas\Components;

use Filament\Forms\Components\TextInput;

class CustomerNameInput
{
    public static function make(): TextInput
    {
        return TextInput::make('name')
            ->label('Full name')
            ->required()
            ->maxLength(255)
            ->placeholder('Enter your full name')
            ->belowContent('This is the name that will be displayed on your profile.');
    }
}

你可以在 Schma 或者表格中使用这个类:

use App\Filament\Resources\Customers\Schemas\Components\CustomerNameInput;
use Filament\Schemas\Schema;

public static function configure(Schema $schema): Schema
{
    return $schema
        ->components([
            CustomerNameInput::make(),
            // ...
        ]);
}

你可以使用多种不同类型的组件来实现这一点。对于这些组件的命名方式或存储位置,并没有强制的规则。不过,这里有一些建议:

  • Schema 组件:这些组件可以位于资源的 Schemas/Components 目录中。它们可以以其所包装的组件命名,例如 CustomerNameInputCustomerCountrySelect
  • 表格列:这些组件可以位于资源的 Tables/Columns 目录中。它们可以以列字段名后跟 Column 命名,例如 CustomerNameColumnCustomerCountryColumn
  • 表格过滤器:这些组件可以位于资源的 Tables/Filters 目录中。它们可以以过滤器后跟 Filter 命名,例如 CustomerCountryFilterCustomerStatusFilter
  • Action:这些组件可以位于资源的 Actions 目录中。它们可以以操作后跟 ActionBulkAction 命名,例如 EmailCustomerActionUpdateCustomerCountryBulkAction

作为进一步的例子,以下是 EmailCustomerAction 类:

namespace App\Filament\Resources\Customers\Actions;

use App\Models\Customer;
use Filament\Actions\Action;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Support\Icons\Heroicon;

class EmailCustomerAction
{
    public static function make(): Action
    {
        return Action::make('email')
            ->label('Send email')
            ->icon(Heroicon::Envelope)
            ->schema([
                TextInput::make('subject')
                    ->required()
                    ->maxLength(255),
                Textarea::make('body')
                    ->autosize()
                    ->required(),
            ])
            ->action(function (Customer $customer, array $data) {
                // ...
            });
    }
}

你可以在页面的 getHeaderActions() 中使用它:

use App\Filament\Resources\Customers\Actions\EmailCustomerAction;

protected function getHeaderActions(): array
{
    return [
        EmailCustomerAction::make(),
    ];
}

或者可以在表格行中使用:

use App\Filament\Resources\Customers\Actions\EmailCustomerAction;
use Filament\Tables\Table;

public static function configure(Table $table): Table
{
    return $table
        ->columns([
            // ...
        ])
        ->recordActions([
            EmailCustomerAction::make(),
        ]);
}
Edit on GitHub

Still need help? Join our Discord community or open a GitHub discussion

Previous
自定义资源页