Filament v4 Unified Schema API: Forms &amp; Infolists | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

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

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

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Filament v4 Schema-Based Forms, Infolists, and the Unified Schema API        On this page       1. [  Why Filament v4 Rewrote the Component Model ](#why-filament-v4-rewrote-the-component-model)
2. [  The Schema Component Tree ](#the-schema-component-tree)
3. [  Extracting a Shared Schema Method ](#extracting-a-shared-schema-method)
4. [  Schema Components in Custom Pages and Widgets ](#schema-components-in-custom-pages-and-widgets)
5. [  What Actually Breaks When Upgrading ](#what-actually-breaks-when-upgrading)
6. [  Namespace changes ](#namespace-changes)
7. [  -&gt;columns() on Section ](#code-gtcolumnscode-on-codesectioncode)
8. [  Custom field getChildComponents() ](#custom-field-codegetchildcomponentscode)
9. [  Takeaways ](#takeaways)

  ![Filament v4 Schema-Based Forms, Infolists, and the Unified Schema API](https://cdn.msaied.com/360/11c59afcba98933101f65c6357f5cd1c.png)

  #filament   #laravel   #filament-v4   #admin-panel  

 Filament v4 Schema-Based Forms, Infolists, and the Unified Schema API 
=======================================================================

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

       Table of contents

  9 sections  

1. [  01   Why Filament v4 Rewrote the Component Model  ](#why-filament-v4-rewrote-the-component-model)
2. [  02   The Schema Component Tree  ](#the-schema-component-tree)
3. [  03   Extracting a Shared Schema Method  ](#extracting-a-shared-schema-method)
4. [  04   Schema Components in Custom Pages and Widgets  ](#schema-components-in-custom-pages-and-widgets)
5. [  05   What Actually Breaks When Upgrading  ](#what-actually-breaks-when-upgrading)
6. [  06   Namespace changes  ](#namespace-changes)
7. [  07   -&gt;columns() on Section  ](#code-gtcolumnscode-on-codesectioncode)
8. [  08   Custom field getChildComponents()  ](#custom-field-codegetchildcomponentscode)
9. [  09   Takeaways  ](#takeaways)

       Why Filament v4 Rewrote the Component Model
-------------------------------------------

In Filament v3 you maintained two parallel trees: `form(Form $form)` returned `$form->schema([...])` and `infolist(Infolist $infolist)` returned `$infolist->schema([...])`. The components were different classes even when they displayed the same data — a `TextInput` for editing, a `TextEntry` for viewing. Filament v4 collapses this into a **unified Schema API** where a single component tree can render in both contexts, and dedicated entry components are first-class citizens alongside field components.

---

The Schema Component Tree
-------------------------

Every layout wrapper — `Section`, `Grid`, `Tabs`, `Fieldset` — now lives under `Filament\Schemas\Components\` and is shared between forms and infolists. You import them once and use them everywhere.

```php
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Grid;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;

public static function form(Form $form): Form
{
    return $form->schema([
        Section::make('Identity')
            ->schema([
                Grid::make(2)->schema([
                    TextInput::make('name')->required(),
                    TextInput::make('email')->email()->required(),
                ]),
            ]),
    ]);
}

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

```

The `Section` and `Grid` imports are identical. Only the leaf components differ.

---

Extracting a Shared Schema Method
---------------------------------

Because layout wrappers are now the same class, you can extract the skeleton into a static helper and swap only the leaves.

```php
private static function identitySchema(array $fields): array
{
    return [
        Section::make('Identity')
            ->schema([
                Grid::make(2)->schema($fields),
            ]),
    ];
}

public static function form(Form $form): Form
{
    return $form->schema(self::identitySchema([
        TextInput::make('name')->required(),
        TextInput::make('email')->email()->required(),
    ]));
}

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

```

This pattern eliminates the structural duplication that plagued v3 resources with large schemas.

---

Schema Components in Custom Pages and Widgets
---------------------------------------------

Custom pages that previously called `$this->form->fill()` now use `HasForms` or `HasInfolists` traits alongside the schema builder. The `$this->form(...)` and `$this->infolist(...)` calls accept the same unified component classes.

```php
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Schemas\Components\Section;

class EditProfilePage extends Page
{
    use InteractsWithForms;

    public function form(Form $form): Form
    {
        return $form
            ->schema([
                Section::make()->schema([
                    TextInput::make('bio')->columnSpanFull(),
                ]),
            ])
            ->statePath('data');
    }
}

```

---

What Actually Breaks When Upgrading
-----------------------------------

### Namespace changes

Any import of `Filament\Forms\Components\Section` or `Filament\Forms\Components\Grid` must move to `Filament\Schemas\Components\`. A project-wide find-and-replace handles most of it.

### `->columns()` on `Section`

In v3 you called `->columns(2)` on `Section` directly. In v4 you wrap children in `Grid::make(2)` instead. The old shorthand still works as a compatibility shim in early v4 releases, but the canonical approach is explicit `Grid`.

### Custom field `getChildComponents()`

If you built custom layout components by extending `Filament\Forms\Components\Component`, the base class has moved. Extend `Filament\Schemas\Components\Component` instead and implement `getChildComponents()` as before.

---

Takeaways
---------

- Layout components (`Section`, `Grid`, `Tabs`) are now shared across forms and infolists under `Filament\Schemas\Components\`.
- Leaf components (`TextInput`, `TextEntry`) remain context-specific but sit inside the same tree.
- Extracting a shared schema skeleton method removes structural duplication across `form()` and `infolist()`.
- The main upgrade cost is namespace replacement and swapping `->columns()` shortcuts for explicit `Grid` wrappers.
- Custom layout components must extend the new base class in `Filament\Schemas\Components\`.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Ffilament-v4-schema-based-forms-infolists-and-the-unified-schema-api-2&text=Filament+v4+Schema-Based+Forms%2C+Infolists%2C+and+the+Unified+Schema+API) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Ffilament-v4-schema-based-forms-infolists-and-the-unified-schema-api-2) 

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

  3 questions  

     Q01  Can I use a single component for both editing and viewing in Filament v4?        Not for leaf components — TextInput is still edit-only and TextEntry is view-only. The unification applies to layout wrappers like Section and Grid, which are now the same class in both contexts. 

      Q02  Do I need to update every resource immediately after upgrading to Filament v4?        Filament v4 ships compatibility shims for the most common v3 form namespace imports, so many resources continue to work. However, the shims are not guaranteed across minor releases, so migrating namespaces early is strongly recommended. 

      Q03  Where should custom layout components extend from in Filament v4?        Extend Filament\Schemas\Components\Component instead of the old Filament\Forms\Components\Component. The API for getChildComponents() and childComponents() remains the same. 

  Continue reading

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

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

 [ ![PostgreSQL CTEs, Window Functions, and Lateral Joins in Laravel](https://cdn.msaied.com/363/8e5685c14467b502c2bcbd62b4f47f64.png) laravel postgresql query-builder 

### PostgreSQL CTEs, Window Functions, and Lateral Joins in Laravel

Go beyond basic Eloquent queries: learn how to harness PostgreSQL CTEs, window functions, and LATERAL joins di...

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

 4 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/postgresql-ctes-window-functions-and-lateral-joins-in-laravel-2) [ ![Eloquent Query Scopes: Global, Local, and Dynamic Scopes Without the Magic Tax](https://cdn.msaied.com/362/ecd807763e4e5019ee04875ba59dc8bc.png) laravel eloquent database 

### Eloquent Query Scopes: Global, Local, and Dynamic Scopes Without the Magic Tax

Query scopes are one of Eloquent's most misused features. This guide shows how to write global, local, and dyn...

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

 4 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/eloquent-query-scopes-global-local-and-dynamic-scopes-without-the-magic-tax) [ ![FrankenPHP, OPcache JIT, and Preloading: Squeezing Real Throughput from Laravel](https://cdn.msaied.com/361/fc51b795acf24849e543d4f941b850a2.png) laravel frankenphp php 

### FrankenPHP, OPcache JIT, and Preloading: Squeezing Real Throughput from Laravel

A practical guide to running Laravel under FrankenPHP with OPcache JIT and preloading enabled — covering worke...

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

 4 Jul 2026     1 min read  

  Read    

 ](https://msaied.com/articles/frankenphp-opcache-jit-and-preloading-squeezing-real-throughput-from-laravel-1) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://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://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://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)
