Filament v3 to v4 Migration: Breaking Changes | 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
==============================================================================

 A hands-on guide to the most impactful Filament v3→v4 breaking changes, with concrete before/after code examples and a repeatable refactor strategy for production panels.

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

ShareCopy linkCopied

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

  On this page +1. [Why v3→v4 Is Not a Minor Bump](#why-v3v4-is-not-a-minor-bump)
2. [1. The Schema API Replaces form() and infolist() Signatures](#1-the-schema-api-replaces-codeformcode-and-codeinfolistcode-signatures)
3. [2. Action Signature Changes](#2-action-signature-changes)
4. [3. Custom Fields: getFormComponent() Is Gone](#3-custom-fields-codegetformcomponentcode-is-gone)
5. [4. Repeatable Refactor Order](#4-repeatable-refactor-order)
6. [5. Gotcha: Panel Provider Boot Order](#5-gotcha-panel-provider-boot-order)
7. [Key Takeaways](#key-takeaways)

 Why v3→v4 Is Not a Minor Bump
-----------------------------

Filament v4 rewrites the form and infolist rendering layer around a unified **Schema API**. If your panels have custom fields, complex resource forms, or bespoke actions, you will touch almost every resource file. The good news: the changes are systematic, and a disciplined refactor order keeps the panel functional throughout.

---

1. The Schema API Replaces `form()` and `infolist()` Signatures
---------------------------------------------------------------

In v3, `form()` received a `Form` instance and `infolist()` received an `Infolist` instance as separate contracts:

```php
// v3
public static function form(Form $form): Form
{
    return $form->schema([
        TextInput::make('name')->required(),
    ]);
}

public static function infolist(Infolist $infolist): Infolist
{
    return $infolist->schema([
        TextEntry::make('name'),
    ]);
}

```

In v4, both collapse into a single `schema()` method on the resource, and components are context-aware — the same schema renders as a form or infolist depending on the page:

```php
// v4
public static function schema(): array
{
    return [
        TextInput::make('name')
            ->required()
            ->formOnly(),          // visible only in form context
        TextEntry::make('name')
            ->infolistOnly(),      // visible only in infolist context
    ];
}

```

For fields that behave identically in both contexts you simply omit the context modifier — the framework resolves the correct renderer automatically.

---

2. Action Signature Changes
---------------------------

v3 table actions accepted a closure receiving the record:

```php
// v3
Tables\Actions\Action::make('approve')
    ->action(fn (Order $record) => $record->approve())
    ->requiresConfirmation(),

```

v4 introduces a typed `ActionArguments` contract and moves confirmation into a fluent builder chain:

```php
// v4
Tables\Actions\Action::make('approve')
    ->action(function (Order $record, array $data): void {
        $record->approve();
    })
    ->confirm(
        title: 'Approve order?',
        description: 'This cannot be undone.',
    ),

```

The `requiresConfirmation()` shorthand still exists as an alias, but the explicit `confirm()` builder gives you translated strings and custom icon support without a modal component.

---

3. Custom Fields: `getFormComponent()` Is Gone
----------------------------------------------

v3 custom field plugins exposed `getFormComponent()` to return a Livewire view. v4 replaces this with a `render()` method that returns a `ComponentRenderer`:

```php
// v3
public function getFormComponent(): string
{
    return 'my-package::colour-swatch';
}

// v4
public function render(): ComponentRenderer
{
    return ComponentRenderer::make(
        view: 'my-package::colour-swatch',
        data: fn () => ['swatches' => $this->getSwatches()],
    );
}

```

This matters because `ComponentRenderer` participates in the deferred-loading pipeline, so your custom field gets lazy hydration for free.

---

4. Repeatable Refactor Order
----------------------------

Do not attempt a big-bang migration. Use this order to keep the panel green at each step:

1. **Upgrade composer deps** — `filament/filament:^4.0` with `--no-scripts` first.
2. **Run the upgrade command** — `php artisan filament:upgrade` patches the most mechanical changes (import paths, method renames).
3. **Fix schema methods** — convert `form()` / `infolist()` to `schema()` resource by resource.
4. **Audit custom fields** — replace `getFormComponent()` with `render()`.
5. **Review action closures** — add explicit type hints; test confirmation dialogs.
6. **Run Pest suite** — Filament's test helpers (`livewire(EditOrder::class)->fillForm([...])->call('save')`) are unchanged in v4, so existing feature tests catch regressions immediately.

---

5. Gotcha: Panel Provider Boot Order
------------------------------------

v4 defers panel registration to `booted()` instead of `boot()`. If you resolve panel-specific services inside `boot()` in a custom service provider, those services may not yet be registered:

```php
// v4-safe: use booted()
public function booted(): void
{
    FilamentAsset::register([
        Js::make('my-plugin', __DIR__ . '/../dist/my-plugin.js'),
    ]);
}

```

---

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

- The unified Schema API is the largest surface-area change; migrate resource by resource, not all at once.
- `php artisan filament:upgrade` handles ~60% of mechanical renames — always run it first.
- Custom field plugins must replace `getFormComponent()` with `ComponentRenderer::make()`.
- Action confirmation moves to the fluent `confirm()` builder; `requiresConfirmation()` still works as an alias.
- Existing Pest/Livewire test helpers are compatible — lean on them to validate each migrated resource before moving to the next.

- [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)
- [filament-v4](https://www.msaied.com/public/articles?search=filament-v4)

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

  Can I migrate resources one at a time without breaking the whole panel?Yes. Filament v4 ships a compatibility shim for the v3 `form()` and `infolist()` signatures that emits a deprecation notice but does not throw. Migrate resource by resource, running your Pest suite after each one.

   Do Filament v3 custom field packages work in v4 without changes?Not without a small update. Any package that implements `getFormComponent()` must replace it with `render(): ComponentRenderer`. The view itself is usually unchanged; only the method signature and return type differ.

   Are Livewire-based Filament tests affected by the v4 upgrade?The test helper API (`livewire(ResourcePage::class)-&gt;fillForm()-&gt;assertFormSet()`) is stable across v3 and v4. Your existing Pest feature tests should pass without modification after migrating a resource's schema.

   ![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 articleLaravel AI SDK: Tool-Calling Agents with Structured Output and Conversation Persistence](https://www.msaied.com/public/articles/laravel-ai-sdk-tool-calling-agents-with-structured-output-and-conversation-persistence) [Next articleStreaming AI Responses in Laravel: Token Budgets, Structured Output, and Production Contracts](https://www.msaied.com/public/articles/streaming-ai-responses-in-laravel-token-budgets-structured-output-and-production-contracts)  

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

1. [Why v3→v4 Is Not a Minor Bump](#why-v3v4-is-not-a-minor-bump)
2. [1. The Schema API Replaces form() and infolist() Signatures](#1-the-schema-api-replaces-codeformcode-and-codeinfolistcode-signatures)
3. [2. Action Signature Changes](#2-action-signature-changes)
4. [3. Custom Fields: getFormComponent() Is Gone](#3-custom-fields-codegetformcomponentcode-is-gone)
5. [4. Repeatable Refactor Order](#4-repeatable-refactor-order)
6. [5. Gotcha: Panel Provider Boot Order](#5-gotcha-panel-provider-boot-order)
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)
