Search

Filament Panels on Laravel 13: Compatibility Checklist

Filament Panels on Laravel 13: Compatibility Checklist

Key takeaways

  • All three maintained Filament lines run on Laravel 13 once you’re on a recent minor: v5 and v4 from spring 2026, and v3 from 3.3.54 (June 2026).
  • Laravel 13 needs PHP 8.3 or newer. Filament itself still accepts PHP 8.2, so PHP is usually the real blocker.
  • Watch for the quiet changes: new session cookie and cache prefix names (everyone is logged out and the cache starts empty), serializable_classes defaulting to false, and domain routes now taking priority over non-domain routes.
  • Update your plugins as well. Many dropped Laravel 11 or require newer PHP when they added Laravel 13 support.

 

Laravel 13 was released on 17 March 2026. Its own upgrade guide estimates about ten minutes for a typical app. A Filament panel adds a few moving parts: the Filament version, plugins, Livewire, and admin users who don’t like being logged out on a Tuesday afternoon. Here’s a checklist you can work through in order.

1. Pick a Filament version that supports Laravel 13

Filament lineLaravel 13 supportNotes
5.xYes, since the 5.4 release (March 2026)Current: 5.8.4. illuminate/contracts: ^11.28|^12.0|^13.0
4.xYes, on recent 4.x releasesCurrent: 4.13.4, same Laravel range, Livewire ^3.7
3.xYes, since 3.3.54 (12 June 2026)Security fixes only now. Bug fixes ended 1 Aug 2026

In practice, move to the latest minor of whichever line you’re on before bumping Laravel:

composer update "filament/*" -W
composer show filament/filament   # confirm the version

If you’re on the early 5.0–5.3 releases, Composer will refuse Laravel 13. That’s the “Can’t install Filament v5 on Laravel 13” error people reported in March 2026. The fix is simply to update Filament.

2. Upgrade PHP to 8.3 or newer

LaravelPHP supportBug fixes untilSecurity fixes until
128.2–8.513 Aug 202624 Feb 2027
138.3–8.5Q3 202717 Mar 2028

Source: Laravel release notes.

Upgrade PHP first and deploy that on its own. Then upgrade Laravel. For the full reasoning, see our explainer Can you run Laravel 13 on PHP 8.2? Our Laravel PHP version compatibility tool shows the whole matrix.

Some Laravel 13-era packages go further than 8.3. For example, spatie/laravel-activitylog v5 and spatie/laravel-permission v7 require PHP 8.4. Current laravel-permission v8 requires 8.3. Check before you choose your PHP version.

3. Update composer.json

The core Laravel constraint changes from the upgrade guide:

{
    "require": {
        "php": "^8.3",
        "laravel/framework": "^13.0",
        "laravel/tinker": "^3.0",
        "filament/filament": "^5.0"
    },
    "require-dev": {
        "laravel/boost": "^2.0",
        "phpunit/phpunit": "^12.0",
        "pestphp/pest": "^4.0"
    }
}

Then:

composer update -W

If Composer fails, composer why-not laravel/framework 13.0 shows which package is blocking the upgrade. Our Composer semver constraint checker helps you read constraints like ^11.28|^12.0|^13.0.

4. Audit your Filament plugins

Many plugins released Laravel 13 support at the same time as dropping older versions. Some examples from Packagist in September 2026:

  • Filament Shield 4.3.x: illuminate/* ^11.28|^12.0|^13.0 and spatie/laravel-permission ^6.0|^7.0|^8.0
  • Filament Spatie Backup 4.x: Laravel 12–13. Laravel 13 with Spatie Backup 10 needs PHP newer than 8.2
  • Badgeable Column 4.1: added Laravel 13 and dropped Laravel 11

Run composer outdated "*filament*" and read each plugin’s release notes for “Laravel 13”.

5. Handle the Laravel 13 changes that affect admin panels

Most of the upgrade guide won’t touch a Filament app. These items will.

CSRF middleware renamed to PreventRequestForgery

VerifyCsrfToken is now PreventRequestForgery. It adds origin checks using the Sec-Fetch-Site header. The old class names remain as deprecated aliases, so nothing breaks today. Update explicit references anyway:

// bootstrap/app.php (Laravel 13 style)
->withMiddleware(function (Middleware $middleware): void {
    $middleware->preventRequestForgery(except: [
        'stripe/*', // e.g. Cashier webhooks
    ]);
})

Filament and Livewire requests carry the CSRF token as normal and need no exclusions. If you run the panel behind an unusual proxy or embed it in an iframe on another origin, test logins and form submissions after deploying.

Session cookie and cache prefix names changed

Laravel 13’s default names use hyphens instead of underscores (laravel-session, laravel-cache-). If you never set these explicitly:

  • All admins are logged out when the cookie name changes.
  • Your cache starts empty under the new prefix. Cached dashboard stats get recomputed at once, so expect a load spike on the first dashboard hits.

To keep the old names, set them explicitly before you deploy:

# Laravel 12 derived these from APP_NAME (slugged with underscores).
# Use the values your production app actually has today.
SESSION_COOKIE=myapp_session
CACHE_PREFIX=myapp_cache_
REDIS_PREFIX=myapp_database_

To find the real values, run php artisan tinker --execute="dump(config('session.cookie'), config('cache.prefix'), config('database.redis.options.prefix'));" on the current production release before upgrading.

Session serialisation now defaults to JSON

The default for session serialisation changes from php to json, which is safer but invalidates active sessions. Keep php if you can’t afford a logout, or combine this change with the cookie rename and log everyone out once.

serializable_classes in the cache config defaults to false

This is a security hardening: PHP objects are no longer unserialised from the cache unless you allow-list them. Filament apps often cache objects without realising it, for example a widget caching a Collection of Eloquent models:

// Before: cached a Collection of models, which is now blocked by default
$top = Cache::remember('dashboard.top-customers', 300, fn () => Customer::top(10)->get());

// Better: cache plain arrays
$top = Cache::remember('dashboard.top-customers', 300,
    fn () => Customer::top(10)->get(['id', 'name', 'lifetime_value'])->toArray());

Alternatively, list the classes you intend to cache in config/cache.php under serializable_classes.

Domain routes now take priority

Laravel 13 matches domain routes before non-domain routes. That matters if you use ->domain() on a panel or ->tenantDomain('{tenant:slug}.example.com') for multi-tenant panels. After upgrading, run php artisan route:list --path=admin and test tenant URLs, the marketing site, and any catch-all routes.

Eloquent: no model instantiation inside boot

Laravel 13 throws a LogicException if a model is instantiated inside another model’s boot or booted method. Old observers and traits sometimes do this, for example static::creating(fn () => new AuditEntry(...)) in the wrong place. Run your create and edit tests.

Polymorphic pivot table names are pluralised

If you have custom morph pivot models without an explicit $table, Laravel 13 may now look for a pluralised name. Set protected $table = '...'; on those pivot models. The Spatie permission and tags tables are configured explicitly, so they’re unaffected.

Smaller changes that show up in tests

  • Str factories reset between tests, so custom UUID/ULID factories must be set in each test’s setup.
  • Js::from() no longer escapes Unicode (\u00e8 becomes è), which affects snapshot-style assertions.
  • upsert() on MySQL/MariaDB throws on an empty uniqueBy. Check custom importers.
  • The JobAttempted event exposes $exception instead of $exceptionOccurred. Listeners that watch Filament import and export jobs need updating.
  • pagination::default is now pagination::bootstrap-3. This only matters if you render Laravel’s paginator views yourself.

6. Static analysis: DB::raw() is stricter

Laravel 13 narrowed the types of Connection::raw() and orderByRaw() to literal strings. Your code still runs, but Larastan will flag interpolated SQL like this, which often turns up in table modifyQueryUsing() callbacks:

// Flagged: interpolated raw SQL
->modifyQueryUsing(fn ($q) => $q->orderByRaw("FIELD(status, {$order})"))

// Better: bindings
->modifyQueryUsing(fn ($q) => $q->orderByRaw('FIELD(status, ?, ?, ?)', ['open', 'pending', 'closed']))

Treat these warnings as security fixes rather than noise.

7. Verify

php artisan optimize:clear
php artisan filament:optimize
php artisan about          # Laravel, PHP and driver versions at a glance
php artisan test --parallel

Then run a manual smoke test: log in, switch tenants, run a search, filter and sort, create and edit a record with file uploads, and trigger an import or export if you use them (these exercise queue batches and notifications).

If you use Laravel Boost, Boost 2.0 adds an /upgrade-laravel-v13 command for supported agents. It’s a useful first pass, but review what it changes.

FAQ

Does Filament v5 support Laravel 13?

Yes. Current 5.x releases accept ^11.28|^12.0|^13.0. If Composer refuses, update Filament to the latest 5.x minor, because early 5.0–5.3 releases predate Laravel 13 support.

Does Filament v3 work with Laravel 13?

Yes, from v3.3.54 (June 2026). But v3 no longer gets bug fixes, so pairing a brand-new framework with an unmaintained admin version is a short-term fix at best.

Why were all my Filament users logged out after upgrading?

Laravel 13 changed the default session cookie name and the session serialisation format. Set SESSION_COOKIE (and keep php serialisation) before deploying if you want to keep existing sessions.

What PHP version do I need for Filament on Laravel 13?

PHP 8.3 or newer, because of Laravel 13. Some plugins and Spatie packages need 8.4.

Sources and further reading


Related on The Web Tier: Filament v4 to v5 upgrade guide · Can you run Laravel 13 on PHP 8.2?

TWT Staff

TWT Staff

Writes about Programming, tech news, discuss programming topics for web developers (and Web designers), and talks about SEO tools and techniques

Your experience on this site will be improved by allowing cookies Cookie Policy