Consejos de calidad de código
Usar clases de esquema y tabla
Dado que muchos métodos de Filament definen tanto la interfaz de usuario como la funcionalidad de la aplicación en un solo método, es fácil terminar con métodos y archivos gigantes. Estos pueden ser difíciles de leer, incluso si tu código tiene un estilo limpio y consistente.
Filament trata de mitigar esto proporcionando clases dedicadas de esquema y tabla cuando generas un recurso. Estas clases tienen un método configure()
que acepta un $schema
o $table
. Luego puedes llamar al método configure()
desde cualquier lugar donde quieras definir un esquema o tabla.
Por ejemplo, si tienes el siguiente archivo 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'),
// ...
]);
}
}
Puedes usarlo en el método form()
del recurso:
use App\Filament\Resources\Customers\Schemas\CustomerForm;
use Filament\Schemas\Schema;
public static function form(Schema $schema): Schema
{
return CustomerForm::configure($schema);
}
Podrías hacer lo mismo para table()
:
use App\Filament\Resources\Customers\Schemas\CustomersTable;
use Filament\Tables\Table;
public static function table(Table $table): Table
{
return CustomersTable::configure($table);
}
O para infolist()
:
use App\Filament\Resources\Customers\Schemas\CustomerInfolist;
use Filament\Schemas\Schema;
public static function infolist(Schema $schema): Schema
{
return CustomerInfolist::configure($schema);
}
Estas clases de esquema y tabla deliberadamente no tienen una clase padre o interfaz por defecto. Si Filament forzara una firma de método para configure()
, no podrías pasar tus propias variables de configuración al método, lo cual podría ser útil si quisieras reutilizar la misma clase en múltiples lugares con pequeños ajustes.
Usar clases de componentes
Incluso si estás usando clases de esquema y tabla para mantener las definiciones de esquema y tabla en sus propios archivos, aún puedes terminar con un método configure()
muy largo. Esto es especialmente cierto si estás usando muchos componentes en tu esquema o tabla, o si los componentes requieren mucha configuración.
Puedes mitigar esto creando clases dedicadas para cada componente. Por ejemplo, si tienes un componente TextInput
que requiere mucha configuración, puedes crear una clase dedicada para él:
namespace App\Filament\Resources\Customers\Schemas\Components;
use Filament\Forms\Components\TextInput;
class CustomerNameInput
{
public static function make(): TextInput
{
return TextInput::make('name')
->label('Nombre completo')
->required()
->maxLength(255)
->placeholder('Ingresa tu nombre completo')
->belowContent('Este es el nombre que se mostrará en tu perfil.');
}
}
Luego puedes usar esta clase en tu esquema o tabla:
use App\Filament\Resources\Customers\Schemas\Components\CustomerNameInput;
use Filament\Schemas\Schema;
public static function configure(Schema $schema): Schema
{
return $schema
->components([
CustomerNameInput::make(),
// ...
]);
}
Podrías hacer esto con varios tipos diferentes de componentes. No hay reglas forzadas sobre cómo estos componentes deberían nombrarse o dónde deberían almacenarse. Sin embargo, aquí tienes algunas ideas:
- Componentes de esquema: Estos podrían vivir en el directorio
Schemas/Components
del recurso. Podrían nombrarse según el componente que están envolviendo, por ejemploCustomerNameInput
oCustomerCountrySelect
. - Columnas de tabla: Estas podrían vivir en el directorio
Tables/Columns
del recurso. Podrían nombrarse según la columna seguida deColumn
, por ejemploCustomerNameColumn
oCustomerCountryColumn
. - Filtros de tabla: Estos podrían vivir en el directorio
Tables/Filters
del recurso. Podrían nombrarse según el filtro seguido deFilter
, por ejemploCustomerCountryFilter
oCustomerStatusFilter
. - Acciones: Estas podrían vivir en el directorio
Actions
del recurso. Podrían nombrarse según la acción seguida deAction
oBulkAction
, por ejemploEmailCustomerAction
oUpdateCustomerCountryBulkAction
.
Como ejemplo adicional, aquí tienes una posible clase 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('Enviar email')
->icon(Heroicon::Envelope)
->schema([
TextInput::make('subject')
->required()
->maxLength(255),
Textarea::make('body')
->autosize()
->required(),
])
->action(function (Customer $customer, array $data) {
// ...
});
}
}
Y podrías usarla en getHeaderActions()
de una página:
use App\Filament\Resources\Customers\Actions\EmailCustomerAction;
protected function getHeaderActions(): array
{
return [
EmailCustomerAction::make(),
];
}
O podrías usarla en una fila de tabla:
use App\Filament\Resources\Customers\Actions\EmailCustomerAction;
use Filament\Tables\Table;
public static function configure(Table $table): Table
{
return $table
->columns([
// ...
])
->recordActions([
EmailCustomerAction::make(),
]);
}