If you've been building Laravel admin panels with Filament, you've probably noticed the project has evolved rapidly. Three major versions in a relatively short window — v3, v4, and now v5 — each with its own philosophy and set of trade-offs. This post breaks down what actually changed, version by version.
Requirements at a Glance
Requirement |
v3 |
v4 |
v5 |
|---|---|---|---|
PHP |
8.1+ |
8.2+ |
8.2+ |
Laravel |
10+ |
11 or 12 |
11 or 12 |
Livewire |
3.x |
3.x |
4.x |
Tailwindcss | 3.x |
4.x |
4.x |
The Schema Unification (v3 → v4)
This is the most significant architectural change in the v3-to-v4 migration, and it touches almost every resource file in your project.
In v3, form components, infolist components, and layout components all lived in separate namespaces:
// v3 — separate namespaces for each context
use Filament\Forms\Components\Section;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\Section; // conflict!
use Filament\Infolists\Components\TextEntry;
In v4/v5, these are unified under Filament\Schemas:
// v4/v5 — unified schema namespace
use Filament\Schemas\Components\Section;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
Actions Get Simpler (v3 → v4)
// v3 — different Action class depending on where you use it
use Filament\Tables\Actions\Action;
use Filament\Forms\Components\Actions\Action;
use Filament\Infolists\Components\Actions\Action;
In v4/v5, all actions collapse to a single namespace:
// v4/v5 — one Action class, works everywhere
use Filament\Actions\Action;
Resource Organisation and Code Structure (v3 → v4)
In v3, resources tended to get monolithic quickly. The form() and table() methods could easily grow to hundreds of lines inside a single resource class.
v4 introduces a proper separation of concerns: resource classes are now generated within dedicated namespaces, and the recommendation is to extract large form and table definitions into their own schema/table class files. For example:
app/
Filament/
Resources/
EnquiryResource.php
EnquiryResource/
Pages/
ListEnquiries.php
CreateEnquiry.php
EditEnquiry.php
Schemas/
EnquiryForm.php ← form definition in its own class
Tables/
EnquiryTable.php ← table definition in its own class
This isn't mandatory, but it's the idiomatic v4/v5 approach — and it makes large resources significantly easier to navigate and test.
Layout Defaults Changed (v3 → v4)
One subtle but impactful change: Grid, Section, and Fieldset components changed their default column span behaviour.
In v3, these components consumed the full width of their parent grid by default. In v4/v5, they consume one column by default — consistent with every other component. If you want the old behaviour, you now need to be explicit:
// v4/v5 — restore full-width behaviour
Section::make('Details')
->columnSpanFull()
->schema([...])
This will silently break the visual layout of existing forms after migration if you don't check for it. The upgrade script doesn't handle this one — you need to audit your layouts manually.
Tenancy Scoping (v3 → v4)
If you're using multi-tenancy, v4 made a meaningful improvement here.
In v3, Filament only automatically scoped queries to the current tenant in three specific places: rendering the resource table, resolving URL parameters, and fetching global search results. Everything else — relation managers, custom pages, actions — required manual scoping.
In v4/v5, the panel automatically scopes all queries to the current tenant, and new records are automatically associated with the current tenant via model events. This eliminates a whole class of security footguns that v3 developers had to consciously guard against.
The Rich Editor Swap (v3 → v4)
| Feature | Filament v3 RichEditor | Filament v5 RichEditor |
|---|---|---|
| Editor engine | Trix | Tiptap |
| Filament version | v3 | v5 |
| Content storage (default) | HTML | HTML |
| JSON storage support | No | Yes (->json()) |
| Toolbar customization | Limited | More flexible |
| Custom blocks | No | Yes |
Merge tags ({{ name }}) | No | Yes |
| Extension ecosystem | Small | Large (Tiptap ecosystem) |
| Structured content support | Limited | Strong |
| Drag-and-drop content blocks | No | Yes |
| Existing HTML compatibility | N/A | Existing Trix HTML usually works |
| Migration effort | — | Usually low, but testing recommended |
| Rendering outside Filament | Standard HTML | HTML or JSON depending on configuration |
| v3 | v5 |
|---|---|
php<br>RichEditor::make('content')<br> ->toolbarButtons([<br> 'bold',<br> 'italic',<br> ]);<br> | php<br>RichEditor::make('content')<br> ->toolbarButtons([<br> 'bold',<br> 'italic',<br> ])<br> ->json();<br> |
Livewire Shift (v3 vs. v4)
| Feature | Livewire 3 | Livewire 4 |
|---|---|---|
| Component structure | PHP class + Blade view | Class/View or Single-File Components |
| Alpine integration | Built-in | Built-in |
wire:model default | Deferred | Deferred |
wire:navigate | ✅ | Improved |
| SPA-like navigation | ✅ | Improved |
| Volt support | Optional | First-class experience |
| Single-File Components | Via Volt | Native SFC support |
wire:show | Basic | Improved |
wire:text | ❌ | ✅ |
$js actions | Limited | Expanded |
| Partial rendering | Component-level | Island architecture |
| Independent updates | Limited | Islands |
| Client-side interactivity | Moderate | Greater |
| Performance | Good | Improved hydration and rendering |
Comments
Post a Comment