Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

clinvest's avatar

Testing FilamentPHP Error - Filament\Infolists\Infolist given

Hello all,

I made filament custom page with a form and some logic. Please find the code of the page below. The form is working properly.

However, when I set some test (code below), I have an error from FilamentPHP and I have no idea how to debug it (seems it comes from FilamentPHP itselft). Any idea?

I use Filament V3.

The error:

FAILED  Tests\Feature\ArtistEntityTest > can edit entity                                                                                                                                                                             TypeError   
  App\Filament\Artist\Pages\EditEntity::form(): Argument #1 ($form) must be of type Filament\Forms\Form, Filament\Infolists\Infolist given, called in /var/www/html/vendor/filament/infolists/src/Concerns/InteractsWithInfolists.php on line 54

  at vendor/filament/forms/src/Concerns/InteractsWithForms.php:358
    354▕             'form',
    355▕         ];
    356▕     }
    357▕ 
  ➜ 358▕     public function form(Form $form): Form
    359▕     {
    360▕         return $form
    361▕             ->schema($this->getFormSchema())
    362▕             ->model($this->getFormModel())

      +10 vendor frames 
  11  tests/Feature/ArtistEntityTest.php:34
  Tests:    1 failed, 2 passed (2 assertions)
  Duration: 1.92s

My custom page code:

<?php

namespace App\Filament\Artist\Pages;

use App\Filament\Common\Components;
use App\Models\Artist;
use App\Models\Entity;
use Exception;
use Filament\Forms\Form;
use Filament\Pages\Page;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Forms\Components\Section;
use Illuminate\Database\Eloquent\Model;
use Filament\Forms\Get;
use Filament\Notifications\Notification;
use Illuminate\Contracts\Support\Htmlable;

use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Concerns\InteractsWithForms;

class EditEntity extends Page implements HasForms
{
    use InteractsWithForms;

    protected static ?string $navigationIcon = 'heroicon-o-currency-euro';

    protected static string $view = 'filament.artist.pages.edit-entity';

    public static function getNavigationGroup(): string
    {
        return __('admin.parameters');
    }

    public function getTitle(): string | Htmlable
    {
        return __('admin.my_billing');
    }

    public static function getNavigationLabel(): string
    {
        return __('admin.my_billing');
    }

    public ?array $entityData = [];

    public Entity $entity;
    public Artist $artist;

    public function mount($artist = null): void
    {

        $this->artist = $artist ?? Filament::getTenant();
        $this->entity = $this->getEntity();

        $this->fillForms();

    }

    protected function getForms(): array
    {
        return [
            'editEntityForm'
        ];
    }
 
    public function editEntityForm(Form $form): Form
    {
        return $form
            ->schema([
                Section::make(__('admin.profile_information'))
                    ->aside()
                    ->description(__('admin.profile_information_description'))
                    ->schema([
                        Components::getEntityLegalForm('legal_form')->live()->required(),
                        Components::getEntityAssociationFields()->visible(fn (Get $get): string => $get('legal_form') == 'association'),
                        Components::getEntityCompanyFields()->visible(fn (Get $get): string => $get('legal_form') == 'company'),
                        Components::getEntitySelfEmployedFields()->visible(fn (Get $get): string => $get('legal_form') == 'self_employed'),
                        Components::getEntityTemporaryWorkerFields()->visible(fn (Get $get): string => $get('legal_form') == 'temporary_worker'),
                        Components::getEntityTemporaryWorkersGroupFields()->visible(fn (Get $get): string => $get('legal_form') == 'temporary_workers_group')
                    ]),
            ])
            ->model($this->entity)
            ->statePath('entityData');
    }
 
    protected function fillForms(): void
    {
        $data = $this->entity ? $this->entity->attributesToArray() : [];
        $this->editEntityForm->fill($data);   
    }

    protected function getUpdateOrCreateEntityFormActions(): array
    {
        return [
            Action::make('updateEntityAction')
                ->label(__('filament-panels::pages/auth/edit-profile.form.actions.save.label'))
                ->submit('updateOrCreateEntity')
        ];
    }

    public function updateOrCreateEntity(): void
    { 
        try {
            $data = $this->editEntityForm->getState();
            $this->handleRecordCreateOrUpdate($this->entity, $data);
        } catch (Halt $exception) {
            return;
        }

        $this->sendSuccessNotification(); 
    }

    protected function getEntity(): ?Entity
    {

        $entity = Entity::find($this->artist->entity_id) ?? Entity::make();

        if ($entity) {
            $this->authorize('view', $entity);
        }
    
        if ($entity && !$entity instanceof Model) {
            throw new Exception('The entity object must be an Eloquent model to allow the entity page to update it.');
        }
 
        return $entity;
    }
 
    protected function handleRecordCreateOrUpdate(Model $record, array $data): Model
    {

        if (!$record->exists) {

            $this->authorize('create', Entity::class);
            $this->authorize('update', $this->artist);

            $record->fill($data);
            $record->save();

            $this->artist->entity()->associate($record);
            $this->artist->save();

            return $record;
        } 
        
        $this->authorize('update', $record);
        $record->update($data);
        return $record;

    }

    private function sendSuccessNotification(): void 
    {
        
        Notification::make()
            ->success()
            ->title(__('filament-panels::pages/auth/edit-profile.notifications.saved.title'))
            ->send();
    }

}

My php unit test code:

/** @test */
    public function can_edit_entity(): void
    {

        $user = User::where('email', '[email protected]')->first();
        $artist = $user->artists->first();

        Livewire::actingAs($user)
            ->test(EditEntity::class, ['artist' => $artist])
            ->fillForm([
                'legal_form' => 'association',
                'name' => 'Association name',
                'identification_number' => 'W123456789'
            ])
            ->call('updateOrCreateEntity')
            ->assertHasNoFormErrors();

        $this->assertDatabaseHas(Entity::class, [
            'legal_form' => 'association',
            'name' => 'Association name',
            'identification_number' => 'W123456789'
        ]);

    }

My components code:

<?php

namespace App\Filament\Common;

use Filament\Forms\Components\Component;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Hidden;
use Illuminate\Validation\Rules\Unique;
use Filament\Forms\Components\Wizard\Step;
use Filament\Forms\Components\Actions\Action;
use Filament\Support\Enums\IconPosition;
use App\Models\Address;
use App\Models\Entity;
use Filament\Forms\Get;
use Filament\Forms\Components\Fieldset;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Section;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;

class Components
{

    public static function getFirstName($field = null)
    {
        return TextInput::make($field)->minLength(1)->maxLength(100)->label(__('admin.first_name'));
    }

    public static function getLastName($field = null)
    {
        return TextInput::make($field)->minLength(1)->maxLength(100)->label(__('admin.last_name'));
    }

    public static function getEntitySiret($field = null)
    {
        return TextInput::make($field)->regex('/^\d{14}$/i')->helperText(__('admin.company_identification_number_helper'))->label(__('admin.company_identification_number'));
    }

    public static function getEntityRna($field = null)
    {
        return TextInput::make($field)->regex('/^W\d{9}$/i')->helperText(__('admin.association_identification_number_helper'))->label(__('admin.association_identification_number'));
    }

    public static function getEntityVat($field = null)
    {
        return TextInput::make($field)->regex('/^(AT)?U\d{8}|(BE)?0\d{9}|(BG)?\d{9,10}|(CY)?\d{8}L|(CZ)?\d{8,10}|(DE)?\d{9}|(DK)?\d{8}|(EE)?\d{9}|(EL|GR)?\d{9}|(ES)?[A-Z]\d{7}[A-Z]|(FI)?\d{8}|(FR)?\d{11}|(GB)?\d{12}|(GB)?GD\d{3}|(GB)?HA\d{3}|(HR)?\d{11}|(HU)?\d{8}|(IE)?\d{7}[A-Z]{1,2}|(IE)?[A-Z]\d{5}[A-Z]|(IT)?\d{11}|(LT)?(\d{9}|\d{12})|(LU)?\d{8}|(LV)?\d{11}|(MT)?\d{8}|(NL)?\d{9}B\d{2}|(PL)?\d{10}|(PT)?\d{9}|(RO)?\d{2,10}|(SE)?\d{12}|(SI)?\d{8}|(SK)?\d{10}$/i')->label(__('admin.vat_number'));
    }

    public static function getEntityName($field = null)
    {
        return TextInput::make($field)->label(__('admin.entity_name'));
    }

    public static function getEmail($field = null)
    {
        return TextInput::make($field)->email()->label(__('admin.email'));
    }

    public static function getEntityLegalForm($field = null)
    {
        return Select::make($field)
            ->options([
                'association' => __('admin.association'),
                'company' => __('admin.company'),
                'temporary_worker' => __('admin.temporary_worker'),
                'temporary_workers_group' => __('admin.temporary_workers_group'),
                'self_employed' => __('admin.self_employed')
            ])
            ->default('company')
            ->label(__('admin.entity_type'));
    }

    public static function getEntityTemporaryWorkers($field = null)
    {
        return Repeater::make($field)
            ->label(__('admin.temporary_workers'))
            ->schema([
                self::getFirstName('first_name')->required(),
                self::getLastName('last_name')->required(),
                self::getEmail('email')->required()
            ])
            ->reorderableWithDragAndDrop(false)
            ->maxItems(15)
            ->addAction(
                fn (Action $action) => $action->label(__('admin.add_temporary_worker')),
            )
            ->deleteAction(
                fn (Action $action) => $action->requiresConfirmation(),
            )
            ->columns(3);
    }

    public static function getEntityAssociationFields()
    {
        return Grid::make(1)
            ->schema([
                self::getEntityName('name')->required(),
                self::getEntityRna('identification_number')->required(),
            ]);
    }

    public static function getEntityCompanyFields()
    {
        return Grid::make(1)
            ->schema([
                self::getEntityName('name')->required(),
                self::getEntitySiret('identification_number')->required(),
                self::getEntityVat('vat')->nullable(),
            ]);
    }

    public static function getEntitySelfEmployedFields()
    {
        return Grid::make(1)
            ->schema([
                self::getFirstName('first_name')->required(),
                self::getLastName('last_name')->required(),
                self::getEntitySiret('identification_number')->required(),
                self::getEntityVat('vat')->nullable(),
            ]);
    }

    public static function getEntityTemporaryWorkerFields()
    {
        return Grid::make(1)
            ->schema([
                self::getFirstName('first_name')->required(),
                self::getLastName('last_name')->required(),
                self::getEmail('email')->required(),
            ]);
    }

    public static function getEntityTemporaryWorkersGroupFields()
    {
        return Grid::make(1)
            ->schema([
                Fieldset::make('Label')
                    ->label(__('admin.main_temporary_worker'))
                    ->schema([
                        self::getFirstName('first_name')->required(),
                        self::getLastName('last_name')->required(),
                        self::getEmail('email')->required(),
                    ])->columns(3),
                Fieldset::make('Label')
                    ->label(__('admin.co_temporary_workers'))
                    ->schema([
                        self::getEntityTemporaryWorkers('extra_data.temporary_workers')->visible(fn (Get $get): string => $get('legal_form') == 'temporary_workers_group')->required()
                    ])->columns(1),
            ]);
    }

}
0 likes
7 replies
LaryAI's avatar
Level 58

The error message indicates that the form() method in the EditEntity class expects an argument of type Filament\Forms\Form, but it is receiving an argument of type Filament\Infolists\Infolist.

To fix this error, you need to make sure that you are passing the correct argument to the form() method. In your code, it seems that you are passing an instance of Filament\Infolists\Infolist instead of Filament\Forms\Form.

Looking at your code, it seems that the editEntityForm() method is the one causing the error. You need to make sure that you are passing an instance of Filament\Forms\Form to this method.

Here's the updated code for the editEntityForm() method:

public function editEntityForm(Form $form): Form
{
    return $form
        ->schema([
            Section::make(__('admin.profile_information'))
                ->aside()
                ->description(__('admin.profile_information_description'))
                ->schema([
                    Components::getEntityLegalForm('legal_form')->live()->required(),
                    Components::getEntityAssociationFields()->visible(fn (Get $get): string => $get('legal_form') == 'association'),
                    Components::getEntityCompanyFields()->visible(fn (Get $get): string => $get('legal_form') == 'company'),
                    Components::getEntitySelfEmployedFields()->visible(fn (Get $get): string => $get('legal_form') == 'self_employed'),
                    Components::getEntityTemporaryWorkerFields()->visible(fn (Get $get): string => $get('legal_form') == 'temporary_worker'),
                    Components::getEntityTemporaryWorkersGroupFields()->visible(fn (Get $get): string => $get('legal_form') == 'temporary_workers_group')
                ]),
        ])
        ->model($this->entity)
        ->statePath('entityData');
}

Make sure that you are passing an instance of Filament\Forms\Form to the editEntityForm() method in your test code as well.

If you are still facing issues, please provide more information about the context and any relevant code that might help in understanding the problem better.

clinvest's avatar

Hi all any idea on this? It seems to be a filament error

xcriss's avatar

I facing the same issue, any update on this?

KalimeroMK's avatar

The error you're encountering seems to be related to a mismatch in expected and provided argument types in your EditEntity::form() method. The error message:

less

TypeError App\Filament\Artist\Pages\EditEntity::form(): Argument #1 ($form) must be of type Filament\Forms\Form, Filament\Infolists\Infolist given
indicates that the method is expecting an argument of type Filament\Forms\Form, but it is receiving an argument of type Filament\Infolists\Infolist. This mismatch is likely due to how Filament's framework is calling or using this method.

Here are some steps to debug and potentially resolve this issue:

  1. Review the Method Signature Ensure that your method signature in EditEntity matches the expected signature in Filament's framework. It seems you have an editEntityForm(Form $form): Form method, but the error suggests it's expecting a form(Form $form): Form method.

  2. Check Filament Version Ensure you are using the correct version of Filament and that your code is compatible with it. If you recently updated Filament, some breaking changes might have occurred.

  3. Examine Filament Documentation Review the Filament documentation for the version you are using, specifically focusing on custom pages and form handling. There might be changes or specific requirements for handling forms in custom pages in the version you are using.

  4. Debugging the Code Place some debugging code (like dd() statements) in your EditEntity class to ensure the correct methods are being called and the types of the arguments being passed. This can help you pinpoint where the type mismatch is occurring.

  5. Check the Filament Source Code If possible, examine the Filament source code, particularly the InteractsWithInfolists.php file mentioned in the error. This might give you more context on what Filament expects and how it's handling forms in custom pages.

  6. Community and Support Channels If you're still stuck, consider reaching out to the Filament community or support channels. They might have more context or have encountered similar issues.

  7. Fallback to an Earlier Version As a temporary measure, if a recent update to Filament caused this issue, consider rolling back to an earlier version where your code was working, until you can resolve the compatibility issue.

  8. Testing Adjustments For your PHPUnit test, ensure that the way you're initializing and testing the EditEntity class aligns with how Filament's testing infrastructure expects it. There might be specific ways to test Filament custom pages that differ from standard Laravel testing practices.

Resolving such issues often involves a combination of debugging, reviewing documentation, and sometimes reaching out to the community or support channels. If the issue persists, more specific information or assistance from the Filament community may be required.

LucasCis92's avatar

Hi! I'm having a similar issue, any update on this?

Please or to participate in this conversation.