Skip to content

Upgrading

From 1.x to 2.x

Version 2.x includes several breaking changes. Follow this guide to upgrade your application.

Requirements

DependencyVersion
PHP^8.3
Laravel^12.0
Filament^5.0
Livewire^4.0
Tailwind CSS^4.0

Step 1: Update qore-admin-base

Update your composer.json to require version 2.x:

json
"qore-works-business/qore-admin-base": "^2.0"

Dev Dependency Bumps

Upgrading to qore 2.x pulls in Livewire ^4.1 (via qore-frontend) and pest-plugin-qore v3.0 (which requires Pest ^4.0). This triggers a cascade of required version bumps in your dev dependencies:

PackageOld VersionNew VersionWhy
qore-works-business/pest-plugin-qore^2.0^3.0Required for Pest ^4.0 support
pestphp/pest^3.0^4.0Required by pest-plugin-qore ^3.0
pestphp/pest-plugin-laravel^3.1^4.0Required by pestphp/pest ^4.0
pestphp/pest-plugin-livewire^3.0^4.0Required by livewire/livewire ^4.1

Note: qore-works-business/pest-plugin-qore latest version is ^3.0 (not ^4.0).

Step 2: Run Filament Automated Upgrade

The first step to upgrade your Filament app is to run the automated upgrade script. This script will automatically upgrade your application to the latest version of Filament and make changes to your code, which handles most breaking changes:

bash
composer require filament/upgrade:"^5.0" -W --dev

vendor/bin/filament-v5

# Run the commands output by the upgrade script, they are unique to your app
composer require filament/filament:"^5.0" -W --no-update
composer update

Important: Some plugins you're using may not be available in v5 just yet. You could temporarily remove them from your composer.json file until they've been upgraded.

Windows PowerShell: Replace ^ with ~ in version constraints if experiencing installation issues.

Step 3: Locale Switch Migration

The locale switch functionality is now built into qore-admin-base. Remove the external package dependency if you are not using it.

Remove from composer.json:

json
// Remove this from "require"
"bezhansalleh/filament-language-switch"

Remove from config/qore.php:

php
// Remove this section if present
'language_switch' => [
    'locales' => ['nl', 'en'],
],

Update your Panel Service Provider:

php
// Before (1.x)
QoreAdminBasePlugin::make()
    ->setFaqResource(true)

// After (2.x)
QoreAdminBasePlugin::make()
    ->setFaqResource(true)
    ->setLocaleSwitch(['nl', 'en'])

Update event imports (if used):

php
// Before
use BezhanSalleh\LanguageSwitch\Events\LocaleChanged;

// After
use QoreWorksBusiness\QoreAdminBase\Events\LocaleChanged;

Step 4: Manual Filament 5 Changes

The automated upgrade tool handles most changes, but some files may need manual updates. Review your Resources, Pages, and custom components for these patterns:

Actions Namespace

ALL table action classes have moved from Filament\Tables\Actions\* to Filament\Actions\*. This includes CreateAction, EditAction, DeleteAction, ForceDeleteAction, RestoreAction, BulkActionGroup, DeleteBulkAction, ForceDeleteBulkAction, RestoreBulkAction, and all others.

php
// Before
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\CreateAction;
use Filament\Tables\Actions\EditAction;
use Filament\Tables\Actions\DeleteAction;
use Filament\Tables\Actions\ForceDeleteAction;
use Filament\Tables\Actions\RestoreAction;
use Filament\Tables\Actions\BulkActionGroup;
use Filament\Tables\Actions\DeleteBulkAction;
use Filament\Tables\Actions\ForceDeleteBulkAction;
use Filament\Tables\Actions\RestoreBulkAction;

// After — ALL moved to Filament\Actions
use Filament\Actions\Action;
use Filament\Actions\CreateAction;
use Filament\Actions\EditAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\ForceDeleteAction;
use Filament\Actions\RestoreAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\ForceDeleteBulkAction;
use Filament\Actions\RestoreBulkAction;

Static Property Types

Filament 5 changed the types of static properties on Resource and Page classes. If your project overrides these properties, the type declarations must be updated or PHP will throw a fatal error:

php
// Before
protected static ?string $navigationGroup = 'Platform';
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';

// After
use BackedEnum;
use UnitEnum;

protected static string | UnitEnum | null $navigationGroup = 'Platform';
protected static string | BackedEnum | null $navigationIcon = 'heroicon-o-rectangle-stack';

Form to Schema

php
// Before
use Filament\Forms\Form;
public static function form(Form $form): Form

// After
use Filament\Schemas\Schema;
public static function form(Schema $schema): Schema

Layout Components

php
// Before
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Grid;

// After
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Grid;

Get/Set Utilities

php
// Before
use Filament\Forms\Get;
use Filament\Forms\Set;

// After
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;

Auth Pages

php
// Before
use Filament\Pages\Auth\Login;

// After
use Filament\Auth\Pages\Login;

Dashboard Page

php
// Before
use Filament\Pages\Page;
class Dashboard extends Page
{
    protected function getWidgets(): array { ... }
}

// After
use Filament\Pages\Dashboard as FilamentDashboard;
class Dashboard extends FilamentDashboard
{
    public function getWidgets(): array { ... }  // Must be public
}

For full details, see the Filament 5 Upgrade Guide.

Step 5: Update Tests for Filament 5

Filament 5 introduces TestAction objects for testing table actions. The old callTableAction() still works but the new callAction() with TestAction is the recommended pattern.

Testing Table Actions

php
use Filament\Actions\Testing\TestAction;

// Table header actions (e.g. create) — no record, just mark as table action
// Before:
$livewire->callTableAction(CreateAction::class, null, $data);
// After:
$livewire->callAction(TestAction::make(CreateAction::class)->table(), $data);

// Table row actions (e.g. detach, edit, delete) — pass the record
// Before:
$livewire->callTableAction('detach', $record);
// After:
$livewire->callAction(TestAction::make('detach')->table($record));

Row Action ->model() Breaking Change

Filament 5 enforces record type checking via ensureCorrectRecordType(). If a row action has ->model(Company::class) but the table record is a Person, getRecord() returns null and the action fails.

Fix: Remove ->model() from row actions that operate on the table's related model:

php
// Before (broken in Filament 5)
DetachAuditAction::make()->model(Company::class),

// After
DetachAuditAction::make(),

Note: ->model() on header actions like AttachAuditAction is still valid because the model is used for record search/selection, not record type checking.

CountrySelect in Tests

Use known-valid country codes instead of fake()->countryCode():

php
// Before (generates codes not in LaravelLang list)
'country_of_birth' => strtolower(fake()->countryCode()),

// After
'country_of_birth' => fake()->randomElement(['nl', 'de', 'be', 'fr', 'gb']),

Step 6: Livewire 4 Updates

After Filament is upgraded, review the Livewire 4 Upgrade Guide for any remaining updates.

Events (most common change):

php
// Before
$this->emit('eventName');

// After
$this->dispatch('eventName');

wire:model ignores child element events by default. Add .deep to restore v3 behavior:

blade
<div wire:model.deep="value">

Configuration (config/livewire.php):

  • 'layout''component_layout'
  • 'lazy_placeholder''component_placeholder'

Step 7: Tailwind CSS v4 Theme Migration

Tailwind CSS v4 uses CSS-first configuration. The old JS-based config with Filament presets no longer works.

Filament Admin Theme

The Filament admin theme CSS file needs updating. The tailwind.config.preset from the filament package no longer exists in Filament 5.

css
/* Before (Tailwind CSS v3) */
@import '../../../../vendor/filament/filament/resources/css/theme.css';

/* tailwind config */
@config './tailwind.config.js';
css
/* After (Tailwind CSS v4) */
@import '../../../../vendor/filament/filament/resources/css/theme.css';

@source '../../../../app/Application/Admin/**/*';
@source '../../../../resources/views/application/admin/**/*';

You can remove the old tailwind.config.js file that referenced the Filament preset.

Portal CSS

Portal CSS should use @source directives instead of JS config content arrays:

css
/* Before (Tailwind CSS v3 — tailwind.config.js) */
content: ['../../../../vendor/qore-works-business/qore-frontend/resources/views/**/*.blade.php']

/* After (Tailwind CSS v4 — app.css) */
@import "tailwindcss";

@source '../../../../vendor/qore-works-business/qore-frontend/resources/views/**/*.blade.php';
@source '../../../../resources/views/application/portal/**/*.blade.php';

Step 8: Update Project Files

Update default stub files and composer scripts using the maintenance commands:

bash
# Update stub files (tests, config) - safe mode first
php artisan qore-admin-base:publish-stubs

# Add missing composer scripts
php artisan qore-admin-base:update-composer-scripts

Tip: Run publish-stubs without --force first to see which files would be updated, then use --force to overwrite specific files as needed.

See the Commands page for full details on these commands.

Step 9: Clear Caches

bash
php artisan optimize:clear
php artisan filament:clear-cached-components

Quick Search Commands

Find files that may still need manual updates:

bash
# Actions namespace
grep -r "use Filament\\Tables\\Actions\\" --include="*.php" .

# Layout components
grep -r "use Filament\\Forms\\Components\\Section" --include="*.php" .

# Get/Set utilities
grep -r "use Filament\\Forms\\Get" --include="*.php" .

# Livewire emit
grep -r "->emit(" --include="*.php" .