FilamentPHP 4 Beta
Publicado por Andrés López

El equipo de Filament ha lanzado finalmente la beta de Filamentphp 4, con unas mejoras increíbles de velocidad y un montón de nuevas herramientas. Abordaré la mayoría de los cambios hasta ahora vistos, aquí tienes un pequeño índice para que no te pierdas nada:
- Como probar la Beta
- General
- Resources
- Navegación
- Schemas
- Forms
- Infolists
- Tables
- Actions
- Widgets
- Dashboard
- Multi tenacy
- Configuración del panel
Como probar la Beta
Puedes revisar la nueva documentación para ver los nuevos cambios.
Para instalar la versión Beta primero tu proyecto debe permitir versiones no estables, corre el siguiente comando en tu aplicación:
composer config minimum-stability beta
Después corre la instalación de Filament
composer require filament/filament:"^4.0"
php artisan filament:install --panels
Y eso es todo, el resto es lo mismo que la versión 3.
General
Rendimiento
El renderizado y la interacción en general ha sido retrabajado y mejorado enormemente, sobre todo a la hora de manejar mucha información, se redujo la cantidad de blade necesario para mostrar componentes, se redujo el HTML y las clases de TailwindCSS utilizadas.
TailwindCSS
Es oficial Filament tiene soporte para la nueva versión de TailwindCSS ahora tendrás que usar oklch
para configurar tus temas:
use Filament\Support\Facades\FilamentColor;
FilamentColor::register([
'danger' => [
50 => 'oklch(0.969 0.015 12.422)',
100 => 'oklch(0.941 0.03 12.58)',
200 => 'oklch(0.892 0.058 10.001)',
300 => 'oklch(0.81 0.117 11.638)',
400 => 'oklch(0.712 0.194 13.428)',
500 => 'oklch(0.645 0.246 16.439)',
600 => 'oklch(0.586 0.253 17.585)',
700 => 'oklch(0.514 0.222 16.935)',
800 => 'oklch(0.455 0.188 13.697)',
900 => 'oklch(0.41 0.159 10.272)',
950 => 'oklch(0.271 0.105 12.094)',
],
]);
Autenticación
Añadieron una de las funcionalidades más solicitadas y es el doble factor de autenticación, soportando aplicaciones como Google Auhtenticator, Authy, etc o puedes usar la implementación de correo para enviar contraseñas de un solo uso.
Aunque es un poco más complicado de lo esperado la implementación sigue siendo bastante más sencillo que implementarlo tu mismo, además de permitirte agregar tu propia lógica:
use Filament\Auth\MultiFactor\App\AppAuthentication;
use Filament\Auth\MultiFactor\Email\EmailAuthentication;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->multiFactorAuthentication([
AppAuthentication::make()
->recoverable()
->recoveryCodeCount(10)
->regenerableRecoveryCodes(false)
->codeWindow(4)
->brandName('Filament Demo'),
EmailAuthentication::make()
->codeExpiryMinutes(2)
], isRequired: true);
}
Heroicons
¿Eres un desquiciado del tipado fuerte? Ahora puedes usar los heroicons como enum:
use Filament\Support\Icons\Heroicon;
Heroicon::OutlinedStar;
Heroicon::Star;
Timezone por defecto
Ahora puedes definir un timezone específico para Filament:
use Filament\Support\Facades\FilamentTimezone;
public function boot(): void
{
FilamentTimezone::set('America/Mexico_City');
}
Resources
Recursos anidados
Ahora por fin puedes añadir recursos anidados, esto es especialmente útil si la relación que estas manejando es demasiado grande para ser creado/editado mediante un modal, ahora puedes crear un recurso anidado para darle una página entera, de cualquier manera se sigue recomendando utilizar relationManagers para manejar el listado de la relación.
Cambio en la organización de archivos
Ahora cada resource tendrá su propio namespace para permitir una mejor organización:
Anteriormente Ahora
Filament/ Filament/
├─Resources/ ├─Resources/
├───UserResource/ ├───Users/
└───UserResource.php └─────UserResource.php
Recomendaciones de código
En toda la documentación agregaron nuevos ejemplos y recomendaciones de como dividir tu código para que sea escalable, entendible y mantenible.
Personalización del contenido
Ahora hay un nuevo método content
para configurar como se ve cada página de listar, crear, editar y ver:
use Filament\Schemas\Components\EmbeddedTable;
use Filament\Schemas\Components\RenderHook;
use Filament\Schemas\Schema;
public function content(Schema $schema): Schema
{
return $schema
->components([
$this->getTabsContentComponent(), // This method returns a component to display the tabs above a table
RenderHook::make(PanelsRenderHook::RESOURCE_PAGES_LIST_RECORDS_TABLE_BEFORE),
EmbeddedTable::make(), // This is the component that renders the table that is defined in this resource
RenderHook::make(PanelsRenderHook::RESOURCE_PAGES_LIST_RECORDS_TABLE_AFTER),
]);
}
Navegación
Sidebar / Topbar
Ahora el sidebar y el topbar de tu panel también son componentes de livewire, permitiendo actualizarlo junto a acciones de livewire:
use Filament\Actions\Action;
use Livewire\Component;
Action::make('create')
->action(function (Component $livewire) {
// ...
$livewire->dispatch('refresh-sidebar');
$livewire->dispatch('refresh-topbar');
})
Schemas
Ahora los forms y los infolists están por debajo de Schema, lo cual los hace compatibles entre los dos:
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Section;
$schema
->components([
Grid::make(2)
->schema([
Section::make('Details')
->schema([
TextInput::make('name'),
Select::make('position')
->options([
'developer' => 'Developer',
'designer' => 'Designer',
]),
Checkbox::make('is_admin'),
]),
Section::make('Auditing')
->schema([
TextEntry::make('created_at')
->dateTime(),
TextEntry::make('updated_at')
->dateTime(),
]),
]),
])
Tabs verticales
Ahora puedes colocar tus tabs de tus formularios e infolist de manera vertical:
use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
Tabs::make('Tabs')
->tabs([
])
->vertical();
Container queries
Con la implementación de TailwindCSS 4 la adición de los container queries tambien serán compatibles con FilamentPHP:
use Filament\Schemas\Components\Grid;
Grid::make()
->gridContainer()
->columns([
'@md' => 3,
'@xl' => 4,
])
->schema([
// ...
])
Forms
Nuevo editor enriquecido
El editor enriquecido de FilamentPHP ahora utilizará Tiptap lo cual da mucho mejores herramientas, permitiendo guardar como json, añadir bloques personalizados, tags personalizadas para tener contenido calculado, extensión de funcionalidades mediante plugins del editor:
Nuevo slider
Ahora puedes usar un slider en tus forms, permitiendo usar rangos menos y mayores totalmente personalizables.
Editor de código
Ahora tienes un editor de código con opción de resaltado de código:
Table repeaters
Una de las mejores adiciones es la mejora de los repeaters que ahora pueden convertirse en tablas:
Javascript para evitar peticiones HTTP
Una de las mayores debilidades de Livewire es la necesidad constante de realizar peticiones HTTP para sincronizar los states de las distintas propiedades y con FilamentPHP esto es un problema aún mayor al tener todo escrito en PHP, con la nueva versión se agregan 2 nuevos métodos: hiddenJs()
y visibleJs()
Toggle::make('is_admin')
->hiddenJs(<<<'JS'
$get('role') !== 'staff'
JS)
Adicional a lo anterior, ahora cuentas con el objeto JsContent que permite evaluar js directamente en cualquier atributo de tus componentes:
use Filament\Forms\Components\TextInput;
use Filament\Schemas\JsContent;
TextInput::make('greetingResponse')
->label(JsContent::make(<<<'JS'
($get('name') === 'John Doe') ? 'Hello, John!' : 'Hello, stranger!'
JS
))
Y por último pero no menos importante también un nuevo método para cuando se actualizan los estados desde js:
use Filament\Forms\Components\TextInput;
TextInput::make('name')
->afterStateUpdatedJs(<<<'JS'
$set('email', ($state ?? '').replaceAll(' ', '.').toLowerCase() + '@example.com')
JS);
Agrupar componentes
Aunque recuerdo que esto ya se podía hacer en Filament 3, esta vez puedes unir aún más componentes:
- text inputs
- selects
- date-time pickers
- color pickers
Contenido extra para todos los componentes
Ahora todos los componentes cuentan con nuevas secciones donde puedes añadir el contenido que necesites:
- aboveLabel(), beforeLabel(), afterLabel(), belowLabel()
- aboveLabel(), beforeLabel(), afterLabel(), belowLabel()
- aboveErrorMessage(), belowErrorMessage()
Estos métodos también aceptan otros componentes:
Renderizado parcial
Anteriormente si necesitabas sincronizar estados entre componentes o mismamente con el backend, tenías que usar el método live()
ahora Filament 4 añade nuevos métodos para solo tomar efecto cuando lo que desees cambie:
partiallyRenderComponentsAfterStateUpdated()
vuelve a renderizar solamente un componente en específico después que el estado se actualizapartiallyRenderAfterStateUpdated()
vuelve a renderizar solamente el componente mismoskipRenderAfterStateUpdated()
previene y vuelve a renderizar.
use Filament\Forms\Components\TextInput;
TextInput::make('name')
->live()
->partiallyRenderComponentsAfterStateUpdated(['email'])
Mejoras en el casting
Si usas casting para tus selects por ejemplo, ahora las utildidades al acceder a esos valores dará instancias del enum y no los string, facilitando la codificación y entendimiento:
Select::make('status')
->label(function(?StatusEnum $state): string {
return $state?->value ?? 'Label';
});
Infolists
Code entry
Ahora puedes mostrar código formateado en tus infolist:
use Filament\Infolists\Components\CodeEntry;
use Phiki\Grammar\Grammar;
CodeEntry::make('code')
->grammar(Grammar::Php)
Tables
Información personalizada
Anteriormente para mostrar información que no proveniera de base de datos era necesario utilizar paquetes como sushi/sushi que aprovechan los modelos para mostrar arrays, con Filament 4 ahora puedes directamente definir tu lógica para mostrar esta información, permitiendo acceder a API (es el ejemplo más claro) e implementar tu propia lógica de obtención de datos:
use Filament\Tables\Table;
use Illuminate\Pagination\LengthAwarePaginator;
public function table(Table $table): Table
{
return $table
->records(function (
?string $sortColumn,
?string $sortDirection,
?string $search,
array $filters,
int $page,
int $recordsPerPage
): LengthAwarePaginator {
...
return new LengthAwarePaginator(
items: $response['products'],
total: $response['total'],
perPage: $recordsPerPage,
currentPage: $page
);
})
->columns([
...
])
->filters([
....
])
->searchable();
}
Columnas visibles todo el tiempo
Ahora aunque no existan datos en las tablas estás mostrarán las columnas, mejorando bastante la experiencia de usuario.
Barra de acciones para tablas
Ahora las tablas contarán con una toolbar donde puedes añadir acciones normales y acciones másivas (bulk actions).
Actions
Acciones unificadas
Ahora ya no necesitas definir un namespace específico para tablas y acciones generales, ahora todas serán Filament\Actions
Bulk actions
Rendimiento
Ahora cuentas con un nuevo método chunkSelectedRecords()
que permite dividr los registros seleccionados por chunks:
use Filament\Actions\BulkAction;
use Illuminate\Support\LazyCollection;
BulkAction::make()
->chunkSelectedRecords(250)
->action(function (LazyCollection $records) {
// Process the records...
})
Autorización
Ahora puedes autorizar registros individualmente acciones mediante policies:
use Filament\Actions\BulkAction;
use Illuminate\Database\Eloquent\Collection;
BulkAction::make('delete')
->requiresConfirmation()
->authorizeIndividualRecords('delete')
->action(fn (Collection $records) => $records->each->delete())
Notificaciones
Ahora las acciones masivas contarán con notificaciones:
use Filament\Actions\BulkAction;
BulkAction::make('delete')
->successNotificationTitle('Deleted users')
->failureNotificationTitle(function (int $successCount, int $totalCount): string {
if ($successCount) {
return "{$successCount} of {$totalCount} users deleted";
}
return 'Failed to delete any users';
})
Rate limit
Ahora las acciones tienen un límite de tiempo para ser ejecutadas nuevamente, lo puedes definir con el método rateLimit()
:
use Filament\Actions\Action;
Action::make('delete')
->rateLimit(5) // minutes
Autorización
Ahora puedes añadir mensajes de autorización en los tooltips y notificaciones:
use Filament\Actions\Action;
Action::make('edit')
->url(fn (): string => route('posts.edit', ['post' => $this->post]))
->authorize('update')
->authorizationTooltip()
->authorizationNotification()
Importar relaciones
Ahora puedes realizar importanciones de relaciones belongsToMany
use Filament\Actions\Imports\ImportColumn;
ImportColumn::make('author')
->relationship()
Acción de exportar
Ahora puedes estilizar las columnas del xlsx y el writter:
use OpenSpout\Common\Entity\Row;
use OpenSpout\Common\Entity\Style\Style;
use OpenSpout\Writer\XLSX\Options;
/**
* @param array<mixed> $values
*/
public function makeXlsxRow(array $values, ?Style $style = null): Row
{
return Row::fromValues($values, $style);
}
public function getXlsxWriterOptions(): ?Options
{
$options = new Options();
$options->setColumnWidth(10, 1);
$options->setColumnWidthForRange(12, 2, 3);
return $options;
}
Tooltips para acciones deshabilitadas
Ahora puedes mostrar un tooltip para indicar las razones de porque una acción esta deshabilitada con el método tooltip()
.
Widgets
Charts colapsables
Ahora los chart widgets se pueden colapsar:
protected bool $isCollapsible = true;
Filtros personalizados para chart widgets
Ahora puedes filtrar la info para in widgets usando el HasFilterSchema
trait.
Dashboard
Ahora soporta el sistema de grid de Filament:
public function getColumns(): int | string | array
{
return [
'md' => 4,
'xl' => 5,
];
}
Multi tenacy
Ahora el multitenacy también se aplica a todos los ciclos y eventos.
Nuevas variantes de reglas
Debido a funcionamientos raros con las reglas unique
y exists
, Filament añade nuevas para respetar el multi tenacy
scopedUnique
scopedExists
Configuración del panel
Fuentes
Ahora la fuente Inter se cargará de manera local.
Modo estricto
Por defecto si Filament no detecta policies permite seguir navagando y usando tus resources, si acticas el modo estricto arrojará una excepción cada que no encuentre una policy.
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->errorNotifications(false);
}
Verificación de cambio de correo
Ahora si tienes activado el perfil en tu panel, para cambiar tu correo tendrás que confirmar mediante un email válido por 60 minutos.
Notificaciones de error
Ahora puedes personalizar como los mensajes de error aparecen en tu panel, incluso por código de error:
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,
);
}
Eso es todo lo nuevo que Filament 4 beta tiene hasta ahora

Andrés López
Gran fan de Laravel, entusiasta de Vue y escritor de cualquier cosa que suene interesante