Filament v3 → v4 Migration: Breaking Changes Guide | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com) [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles  ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

  [ home ](https://www.msaied.com)    [ articles ](https://www.msaied.com/articles)    Filament v3 to v4 Migration: Breaking Changes and Practical Refactor Patterns        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)

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

  #filament   #laravel   #upgrade   #php  

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

     22 Aug 2026      4 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   Why v4 Is Not a Cosmetic Upgrade  ](#why-v4-is-not-a-cosmetic-upgrade)
2. [  02   1. Panel Provider Bootstrap Changes  ](#1-panel-provider-bootstrap-changes)
3. [  03   2. Schema API: Forms and Infolists Unified  ](#2-schema-api-forms-and-infolists-unified)
4. [  04   3. Action Closure Signatures  ](#3-action-closure-signatures)
5. [  05   4. Table Column Extractions  ](#4-table-column-extractions)
6. [  06   5. Testing After Migration  ](#5-testing-after-migration)
7. [  07   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.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Ffilament-v3-to-v4-migration-breaking-changes-and-practical-refactor-patterns-2&text=Filament+v3+to+v4+Migration%3A+Breaking+Changes+and+Practical+Refactor+Patterns) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Ffilament-v3-to-v4-migration-breaking-changes-and-practical-refactor-patterns-2) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  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. 

      Q02  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. 

      Q03  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. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://www.msaied.com/articles) 

 [ ![Streaming AI Responses in Laravel: Token Budgets, Structured Output, and Agent Contracts](https://cdn.msaied.com/584/3ffe135721c65ab3f9b40401dc3c41de.png) laravel ai llm 

### Streaming AI Responses in Laravel: Token Budgets, Structured Output, and Agent Contracts

Learn how to stream LLM responses in Laravel, enforce token budgets, and lock structured output to typed PHP c...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 23 Aug 2026     4 min read  

  Read    

 ](https://www.msaied.com/articles/streaming-ai-responses-in-laravel-token-budgets-structured-output-and-agent-contracts) [ ![Typed PHP 8.3 Enums as Eloquent Casts, Route Parameters, and Validation Rules](https://cdn.msaied.com/583/7301900aac0f2ec5d1347df11ce92188.png) laravel php8.3 enums 

### Typed PHP 8.3 Enums as Eloquent Casts, Route Parameters, and Validation Rules

Go beyond basic enum casting. Learn how to wire PHP 8.3 backed enums into Eloquent, route model binding, and c...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 23 Aug 2026     1 min read  

  Read    

 ](https://www.msaied.com/articles/typed-php-83-enums-as-eloquent-casts-route-parameters-and-validation-rules) [ ![Livewire v3 Lazy Components, Islands, and Deferred Loading in Practice](https://cdn.msaied.com/582/564b2d098d2b94b53d4f5319ac77d58b.png) livewire laravel performance 

### Livewire v3 Lazy Components, Islands, and Deferred Loading in Practice

Lazy components, islands, and deferred loading in Livewire v3 let you ship fast initial pages without sacrific...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 23 Aug 2026     1 min read  

  Read    

 ](https://www.msaied.com/articles/livewire-v3-lazy-components-islands-and-deferred-loading-in-practice-1) 

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

Explore

- [Home](https://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
