Filament v3 → v4 Migration: Breaking Changes Guide | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. Filament v3 to v4 Migration: Breaking Changes and Practical Refactor Patterns

 Filament v3 to v4 Migration: Breaking Changes and Practical Refactor Patterns
==============================================================================

 Upgrading from Filament v3 to v4 touches forms, tables, actions, and the panel provider API. This guide walks through the real breaking changes with before/after code so you can migrate confidently.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 22 Aug 2026 · Updated 22 Aug 2026 · 4 min read

ShareCopy linkCopied

 ![Filament v3 to v4 Migration: Breaking Changes and Practical Refactor Patterns](https://cdn.msaied.com/579/88c4b61835f17b2248e3e39a0e3e765f.png) 

  On this page +1. [Why v4 Is Not a Cosmetic Upgrade](#why-v4-is-not-a-cosmetic-upgrade)
2. [1. Panel Provider Bootstrap Changes](#1-panel-provider-bootstrap-changes)
3. [2. Schema API: Forms and Infolists Unified](#2-schema-api-forms-and-infolists-unified)
4. [3. Action Closure Signatures](#3-action-closure-signatures)
5. [4. Table Column Extractions](#4-table-column-extractions)
6. [5. Testing After Migration](#5-testing-after-migration)
7. [Key Takeaways](#key-takeaways)

 Why v4 Is Not a Cosmetic Upgrade
--------------------------------

Filament v4 ships a unified **Schema API** that collapses the previously separate form and infolist component trees into a single composable layer. If your codebase leans heavily on custom field classes, render hooks, or action closures, you will feel every one of those changes. This article focuses on the concrete diff — what breaks, why, and how to fix it.

---

1. Panel Provider Bootstrap Changes
-----------------------------------

v3 registered panels inside `AppServiceProvider` or a dedicated `PanelProvider` that extended `PanelProvider` directly.

v4 requires every panel class to implement `HasForms`, `HasTables`, and `HasActions` via the new `InteractsWithForms` concern **at the panel level**, not just on Livewire components.

```php
// v3
class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path('admin')
            ->resources([UserResource::class]);
    }
}

// v4 — note the explicit ->spa() and ->unsavedChangesAlerts() moves
class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path('admin')
            ->spa()                      // moved from plugin config
            ->unsavedChangesAlerts()    // moved from config
            ->resources([UserResource::class]);
    }
}

```

The `->spa()` and `->unsavedChangesAlerts()` calls were previously buried in `config/filament.php`. They are now first-class panel fluent methods.

---

2. Schema API: Forms and Infolists Unified
------------------------------------------

The biggest conceptual shift. In v3, `Forms\Components\*` and `Infolists\Components\*` were parallel but separate namespaces. In v4 both resolve through `Filament\Schemas\Components\*`.

```php
// v3 form schema
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Select;

public static function form(Form $form): Form
{
    return $form->schema([
        TextInput::make('name')->required(),
        Select::make('role')->options(Role::class),
    ]);
}

// v4 — same components, new namespace, Form still accepted
use Filament\Schemas\Components\TextInput;
use Filament\Schemas\Components\Select;

public static function form(Form $form): Form
{
    return $form->schema([
        TextInput::make('name')->required(),
        Select::make('role')->options(Role::class),
    ]);
}

```

The `Form` and `Infolist` wrapper objects remain, but they now both accept `Schema` components. A Rector rule ships with v4 to automate the namespace rewrite — run it first:

```bash
vendor/bin/rector process app --config vendor/filament/filament/rector.php

```

---

3. Action Closure Signatures
----------------------------

v3 actions injected the record via a `$record` parameter resolved by name. v4 uses typed injection exclusively.

```php
// v3
Action::make('approve')
    ->action(function ($record, array $data): void {
        $record->approve($data['note']);
    });

// v4 — type-hint required; $data still works as named param
Action::make('approve')
    ->action(function (Post $record, array $data): void {
        $record->approve($data['note']);
    });

```

Untyped `$record` parameters now throw a `BindingResolutionException` at runtime. The fix is mechanical but must be applied across every resource, relation manager, and custom page.

---

4. Table Column Extractions
---------------------------

`TextColumn::make()` no longer accepts raw HTML via `->html()` by default — it must be explicitly opted in and sanitised:

```php
// v4
TextColumn::make('bio')
    ->html()
    ->sanitizeHtml(); // new — strips disallowed tags via HTMLPurifier

```

Omitting `->sanitizeHtml()` when `->html()` is set triggers a deprecation warning in v4 and will become an exception in v4.x.

---

5. Testing After Migration
--------------------------

Filament's Pest helpers are largely unchanged, but the component class paths in `livewire()` calls must reflect the new panel structure:

```php
it('can approve a post', function () {
    $post = Post::factory()->create();

    livewire(PostResource\Pages\EditPost::class, ['record' => $post->getRouteKey()])
        ->callAction('approve', data: ['note' => 'Looks good'])
        ->assertHasNoActionErrors();

    expect($post->fresh()->status)->toBe(PostStatus::Approved);
});

```

No changes needed here — the Pest helpers abstract the internal wiring.

---

Key Takeaways
-------------

- Run the bundled Rector config first; it handles ~70% of namespace rewrites automatically.
- Type-hint every action closure's `$record` parameter — untyped injection is gone.
- `->spa()` and `->unsavedChangesAlerts()` move into the panel fluent chain.
- `TextColumn::html()` now requires an explicit `->sanitizeHtml()` opt-in.
- Pest-based Filament tests need minimal changes; focus migration effort on resource and action PHP files.

- [filament](https://www.msaied.com/public/articles?search=filament)
- [laravel](https://www.msaied.com/public/articles?search=laravel)
- [upgrade](https://www.msaied.com/public/articles?search=upgrade)
- [php](https://www.msaied.com/public/articles?search=php)

 Frequently asked questions 
---------------------------

  Can I run Filament v3 and v4 resources side by side during migration?No. Filament v4 is a full panel-level upgrade. You cannot mix v3 and v4 resource classes within the same panel. The recommended approach is to migrate one panel at a time if you run multiple panels.

   Does the Rector config handle action closure signature changes automatically?No. The Rector config only rewrites component namespaces. Action closure type-hint additions must be done manually or with a custom Rector rule, because Rector cannot infer the correct Eloquent model type from context alone.

   Is -&gt;sanitizeHtml() backed by HTMLPurifier or a custom implementation?Filament v4 uses its own configurable sanitiser that wraps a subset of HTMLPurifier defaults. You can extend the allowed tag set via the FilamentSanitizer facade if your content legitimately requires additional HTML elements.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

[Mohamed Said](https://www.msaied.com/public#person)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

[About](https://www.msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articleFilament v4 Render Hooks: Injecting UI Into Any Panel Without Hacking Core](https://www.msaied.com/public/articles/filament-v4-render-hooks-injecting-ui-into-any-panel-without-hacking-core) [Next articleLaravel Reverb in Production: Scaling WebSockets Beyond a Single Server](https://www.msaied.com/public/articles/laravel-reverb-in-production-scaling-websockets-beyond-a-single-server-1)  

   On this page
-------------

1. [Why v4 Is Not a Cosmetic Upgrade](#why-v4-is-not-a-cosmetic-upgrade)
2. [1. Panel Provider Bootstrap Changes](#1-panel-provider-bootstrap-changes)
3. [2. Schema API: Forms and Infolists Unified](#2-schema-api-forms-and-infolists-unified)
4. [3. Action Closure Signatures](#3-action-closure-signatures)
5. [4. Table Column Extractions](#4-table-column-extractions)
6. [5. Testing After Migration](#5-testing-after-migration)
7. [Key Takeaways](#key-takeaways)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://www.msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/740/cce86edc21eddcbdd2f2454fadaf9c70.png)  · 3 min read### The Pipeline Pattern in Laravel: Custom Pipelines Beyond Middleware

5 Oct 2026 ](https://www.msaied.com/public/articles/the-pipeline-pattern-in-laravel-custom-pipelines-beyond-middleware-1) [ ![](https://cdn.msaied.com/739/2d6897fdcdcf090613f96f72a64b8a78.png)  · 4 min read### MySQL Full-Text Search in Laravel: Indexes, Relevance Scoring, and Boolean Mode

4 Oct 2026 ](https://www.msaied.com/public/articles/mysql-full-text-search-in-laravel-indexes-relevance-scoring-and-boolean-mode) [ ![](https://cdn.msaied.com/738/073696a3fefe18bec825beec5ac658f5.png)  · 4 min read### Laravel Queue Rate-Limited Middleware: Throttling Jobs Without Losing Work

4 Oct 2026 ](https://www.msaied.com/public/articles/laravel-queue-rate-limited-middleware-throttling-jobs-without-losing-work) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://www.msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://www.msaied.com/public)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://www.msaied.com/public/sitemap.xml)
