Upgrade guide
NOTE
If you see anything missing from this guide, please do not hesitate to make a pull request to our repository! Any help is appreciated!
New requirements
- PHP 8.2+
- Laravel v11.28+
- Tailwind CSS v4.0+, if you are currently using Tailwind CSS v3.0 with Filament. This does not apply if you are just using a Filament panel without a custom theme CSS file.
- Filament no longer requires
doctrine/dbal
, but if your application still does, and you do not have it installed directly, you should add it to yourcomposer.json
file.
Running the automated upgrade script
NOTE
The upgrade script is not a replacement for the upgrade guide. It handles many small changes that are not mentioned in the upgrade guide, but it does not handle all breaking changes. You should still read the manual upgrade steps to see what changes you need to make to your code.
The first step to upgrade your Filament app is to run the automated upgrade script. Since Filament v4 is in beta, you will need to set the minimum-stability
in your composer.json
file to be beta
before installing any packages. Either adjust it manually or via CLI:
composer config minimum-stability beta
Your composer.json
should look like this:
{
"minimum-stability": "beta"
}
This script will automatically upgrade your application to the latest version of Filament and make changes to your code, which handles most breaking changes:
composer require filament/upgrade:"^4.0" -W --dev
vendor/bin/filament-v4
NOTE
When using Windows PowerShell to install Filament, you may need to run the command below, since it ignores ^
characters in version constraints:
composer require filament/upgrade:"~4.0" -W --dev
vendor/bin/filament-v4
NOTE
If installing the upgrade script fails, make sure that your PHPStan version is at least v2, or your Larastan version is at least v3. The script uses Rector v2, which requires PHPStan v2 or higher.
Make sure to carefully follow the instructions, and review the changes made by the script. You may need to make some manual changes to your code afterwards, but the script should handle most of the repetitive work for you.
You can now composer remove filament/upgrade
as you don't need it anymore.
NOTE
Some plugins you're using may not be available in v4 just yet. You could temporarily remove them from your composer.json
file until they've been upgraded, replace them with a similar plugins that are v4-compatible, wait for the plugins to be upgraded before upgrading your app, or even write PRs to help the authors upgrade them.
Publishing the configuration file
Some changes in Filament v4 can be reverted using the configuration file. If you haven't published the configuration file yet, you can do so by running the following command:
php artisan vendor:publish --tag=filament-config
Firstly, the default_filesystem_disk
in v4 is set to the FILESYSTEM_DISK
variable instead of FILAMENT_FILESYSTEM_DISK
. To preserve the v3 behavior, make sure you use this setting:
return [
// ...
'default_filesystem_disk' => env('FILAMENT_FILESYSTEM_DISK', 'public'),
// ...
]
v4 introduces some changes to how Filament generates files. A new file_generation
section has been added to the v4 configuration file, so that you can revert back to the v3 style if you would like to keep new code consistent with how it looked before upgrading. If your configuration file doesn't already have a file_generation
section, you should add it yourself, or re-publish the configuration file and tweak it to your liking:
use Filament\Support\Commands\FileGenerators\FileGenerationFlag;
return [
// ...
'file_generation' => [
'flags' => [
FileGenerationFlag::EMBEDDED_PANEL_RESOURCE_SCHEMAS, // Define new forms and infolists inside the resource class instead of a separate schema class.
FileGenerationFlag::EMBEDDED_PANEL_RESOURCE_TABLES, // Define new tables inside the resource class instead of a separate table class.
FileGenerationFlag::PANEL_CLUSTER_CLASSES_OUTSIDE_DIRECTORIES, // Create new cluster classes outside of their directories.
FileGenerationFlag::PANEL_RESOURCE_CLASSES_OUTSIDE_DIRECTORIES, // Create new resource classes outside of their directories.
FileGenerationFlag::PARTIAL_IMPORTS, // Partially import components such as form fields and table columns instead of importing each component explicitly.
],
],
// ...
]
Breaking changes that must be handled manually
To begin, filter the upgrade guide for your specific needs by selecting only the packages that you use in your project:
This package is also often used in a panel, or using the tables or actions package.
This package is also often used in a panel, or using the tables or actions package.
This package is also often used in a panel.
This package is also often used in a panel.
This package is also often used in a panel.
This package is also often used in a panel.
High-impact changes
File visibility is now private by default
In addition to the default disk being changed to local
, the file visibility settings across various components have been changed to private
instead of public
by default.
When Filament was first created, Laravel did not have a way to generate temporary signed URLs for local files. As such, the default disk for Filament was set to public
, and the visibility of file uploads was set to public
as well to ease the development experience without additional configuration.
However, Laravel 11 introduced a new "Local Temporary URLs" feature which is enabled by default. Users who created their project before this feature was added may have to update their config/filesystems.php
file to enable it.
In v4, the default disk for Filament is set to local
, and the visibility of file uploads is set to private
by default. This means that files are not publicly accessible by default, and you need to generate a temporary signed URL to access them. This change affects the following components:
FileUpload
form field, includingSpatieMediaLibraryFileUpload
ImageColumn
table column, includingSpatieMediaLibraryImageColumn
ImageEntry
infolist entry, includingSpatieMediaLibraryImageEntry
TIP
You can preserve the old default behavior across your entire app by adding the following code in the boot()
method of a service provider like AppServiceProvider
:
use Filament\Forms\Components\FileUpload;
use Filament\Infolists\Components\ImageEntry;
use Filament\Tables\Columns\ImageColumn;
FileUpload::configureUsing(fn (FileUpload $fileUpload) => $fileUpload
->visibility('public'));
ImageColumn::configureUsing(fn (ImageColumn $imageColumn) => $imageColumn
->visibility('public'));
ImageEntry::configureUsing(fn (ImageEntry $imageEntry) => $imageEntry
->visibility('public'));
Custom themes need to be upgraded to Tailwind CSS v4
Previously, custom theme CSS files contained this:
@import '../../../../vendor/filament/filament/resources/css/theme.css';
@config 'tailwind.config.js';
Now, they should contain this:
@import '../../../../vendor/filament/filament/resources/css/theme.css';
@source '../../../../app/Filament';
@source '../../../../resources/views/filament';
This will load Tailwind CSS. The @source
entries tell Tailwind where to find the classes that are used in your app. You should check the content
paths in your old tailwind.config.js
file, and add them as @source
entries like this. You don't need to include vendor/filament
as a @source
, but check plugins you have installed to see if they require @source
entries.
Finally, you should use the Tailwind upgrade tool to automatically adjust your configuration files to use Tailwind v4, and install Tailwind v4 packages to replace Tailwind v3 ones:
npx @tailwindcss/upgrade
The tailwind.config.js
file for your theme is no longer used, since Tailwind CSS v4 defines configuration in CSS. Any customizations you made to the tailwind.config.js
file should be added to the CSS file.
Changes to table filters are deferred by default
The deferFilters()
method from Filament v3 is now the default behavior in Filament v4, so users must click a button before the filters are applied to the table. To disable this behavior, you can use the deferFilters(false)
method.
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->deferFilters(false);
}
TIP
You can preserve the old default behavior across your entire app by adding the following code in the boot()
method of a service provider like AppServiceProvider
:
use Filament\Tables\Table;
Table::configureUsing(fn (Table $table) => $table
->deferFilters(false));