由于许多 Filament 方法在一个方法中同时定义了应用的 UI 和功能,这很容易导致方法和文件变得臃肿。这些可能难以阅读,即使你的代码风格干净且一致。
Filament 试图通过在生成资源时提供专用的 schema 和 table 类来缓解其中一些问题。这些类拥有一个 configure() 方法,该方法接受一个 $schema 或 $table。然后你可以从任何你想要定义 schema 或 table 的地方调用 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);
}这些 schema 和 table 类默认情况下故意没有父类或接口。如果 Filament 强制执行 configure() 方法的方法签名,你将无法向该方法传递你自己的配置变量,这在你想在多个地方重用同一个类但需要进行细微调整时会很有用。
即使你正在使用模式和表类将模式和表定义保存在各自的文件中,你的 configure() 方法仍然可能变得非常长。如果你在模式或表中使用了大量组件,或者这些组件需要大量配置,情况尤其如此。
你会在理解一个工具能够解决什么问题、它的局限性在哪里,以及它是如何实现以前难以或不可能实现的解决方案时,领会到它的潜力。
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.');
}
}然后你就可以在你的 schema 或 table 中使用这个类:
use App\Filament\Resources\Customers\Schemas\Components\CustomerNameInput;
use Filament\Schemas\Schema;
public static function configure(Schema $schema): Schema
{
return $schema
->components([
CustomerNameInput::make(),
// ...
]);
}你可以使用多种不同类型的组件来完成此操作。对于这些组件应如何命名或存储在何处,没有强制规定。但是,这里有一些想法:
Schemas/Components 目录中。 它们可以根据它们所包装的组件命名,例如 CustomerNameInput 或 CustomerCountrySelect。Tables/Filters目录中。它们可以根据过滤器命名,后跟Filter,例如CustomerCountryFilter或CustomerStatusFilter。Actions目录中。它们可以根据操作命名,后接Action或BulkAction,例如EmailCustomerAction或UpdateCustomerCountryBulkAction。作为进一步的示例,这是一个潜在的 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(),
]);
}