If you have multiple panels in Filament, they may be different with only a few settings like URL and colors. All the other functions in the Panel Provider would be the same, so how to avoid repeating them? This tutorial will show three different solution options.
In the first option, we have a PHP class with the applyCommon()
method, which accepts the panel and PHP enum classes as parameters. In the enum, you would add panel settings like their name, path, etc.
For example, enum could look like this:
app/Enums/Platform.php:
use Filament\Support\Contracts\HasLabel; enum Platform: string implements HasLabel{ case Booking = 'booking'; case Hotel = 'hotel'; public function getLabel(): ?string { return match ($this) { self::Booking => 'Booking Panel', self::Hotel => 'Hotel Panel', }; }}
The common class with the same settings for all panels would look like this:
app/Providers/Filament/Common.php:
use Filament\Panel;use Filament\Pages;use Filament\Widgets;use App\Enums\Platform;use Filament\Support\Colors\Color;use Filament\Http\Middleware\Authenticate;use Illuminate\Session\Middleware\StartSession;use Illuminate\Cookie\Middleware\EncryptCookies;use Illuminate\Routing\Middleware\SubstituteBindings;use Illuminate\Session\Middleware\AuthenticateSession;use Illuminate\View\Middleware\ShareErrorsFromSession;use Filament\Http\Middleware\DisableBladeIconComponents;use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;use Filament\Http\Middleware\DispatchServingFilamentEvent;use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; class Common{ public static function applyCommon(Panel $panel, Platform $platform): Panel { return $panel ->id($platform->value) ->path($platform->value) ->login() ->colors([ 'primary' => Color::Amber, ]) ->pages([ Pages\Dashboard::class, ]) ->widgets([ Widgets\AccountWidget::class, Widgets\FilamentInfoWidget::class, ]) ->middleware([ EncryptCookies::class, AddQueuedCookiesToResponse::class, StartSession::class, AuthenticateSession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, SubstituteBindings::class, DisableBladeIconComponents::class, DispatchServingFilamentEvent::class, ]) ->authMiddleware([ Authenticate::class, ]); }}
In every panel provider, you would now call that applyCommon()
method and then add all other settings unique to this panel.
use Filament\Panel;use App\Enums\Platform;use Filament\PanelProvider; class BookingPanelProvider extends PanelProvider{ public function panel(Panel $panel): Panel { $panel = Common::applyCommon($panel, Platform::Booking); return $panel ->registration() ->topNavigation() ->discoverResources(in: app_path('Filament/Booking/Resources'), for: 'App\\Filament\\Booking\\Resources') ->discoverPages(in: app_path('Filament/Booking/Pages'), for: 'App\\Filament\\Booking\\Pages') ->discoverWidgets(in: app_path('Filament/Booking/Widgets'), for: 'App\\Filament\\Booking\\Widgets'); }}
This idea is from a @PatricioOnCode.
The GitHub repository for this option can be found here.
In the second option, we have a core panel where all the same settings are set. Then, we have a trait to register the core panel. You only need to add this trait to every panel provider.
The core panel could look like this:
app/Providers/Filament/CorePanel.php:
use Filament\Panel;use Filament\Pages;use Filament\Widgets;use Filament\Support\Colors\Color;use Filament\Http\Middleware\Authenticate;use Illuminate\Session\Middleware\StartSession;use Illuminate\Cookie\Middleware\EncryptCookies;use Illuminate\Routing\Middleware\SubstituteBindings;use Illuminate\Session\Middleware\AuthenticateSession;use Illuminate\View\Middleware\ShareErrorsFromSession;use Filament\Http\Middleware\DisableBladeIconComponents;use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;use Filament\Http\Middleware\DispatchServingFilamentEvent;use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; class CorePanel extends Panel{ protected function setUp(): void { $this ->login() ->colors([ 'primary' => Color::Amber, ]) ->pages([ Pages\Dashboard::class, ]) ->widgets([ Widgets\AccountWidget::class, Widgets\FilamentInfoWidget::class, ]) ->middleware([ EncryptCookies::class, AddQueuedCookiesToResponse::class, StartSession::class, AuthenticateSession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, SubstituteBindings::class, DisableBladeIconComponents::class, DispatchServingFilamentEvent::class, ]) ->authMiddleware([ Authenticate::class, ]); }}
The trait to register core panel:
app/Providers/Filament/Traits/HasCorePanel.php:
use Filament\Facades\Filament;use App\Providers\Filament\CorePanel; trait HasCorePanel{ public function register(): void { Filament::registerPanel( $this->panel(CorePanel::make()), ); }}
In every panel, we call this trait to add common settings.
use Filament\Panel;use Filament\PanelProvider;use App\Providers\Filament\Traits\HasCorePanel; class BookingPanelProvider extends PanelProvider{ use HasCorePanel; public function panel(Panel $panel): Panel { return $panel ->id('booking') ->path('booking') ->registration() ->topNavigation() ->discoverResources(in: app_path('Filament/Booking/Resources'), for: 'App\\Filament\\Booking\\Resources') ->discoverPages(in: app_path('Filament/Booking/Pages'), for: 'App\\Filament\\Booking\\Pages') ->discoverWidgets(in: app_path('Filament/Booking/Widgets'), for: 'App\\Filament\\Booking\\Widgets'); }}
This idea is from a @_LukasFrey.
The GitHub repository for this option can be found here.
For the third option, we can utilize a plugin for common settings. We need to create a plugin class that implements the Filament\Contracts\Plugin
. In the register()
, you can add all the common settings as you would in the panel provider.
use Filament\Panel;use Filament\Pages;use Filament\Widgets;use Filament\Contracts\Plugin;use Filament\Support\Colors\Color;use Filament\Http\Middleware\Authenticate;use Illuminate\Session\Middleware\StartSession;use Illuminate\Cookie\Middleware\EncryptCookies;use Illuminate\Routing\Middleware\SubstituteBindings;use Illuminate\Session\Middleware\AuthenticateSession;use Illuminate\View\Middleware\ShareErrorsFromSession;use Filament\Http\Middleware\DisableBladeIconComponents;use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;use Filament\Http\Middleware\DispatchServingFilamentEvent;use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; class CoreSettingsPlugin implements Plugin{ public function getId(): string { return 'app-core-settings'; } public function register(Panel $panel): void { $panel ->login() ->colors([ 'primary' => Color::Amber, ]) ->pages([ Pages\Dashboard::class, ]) ->widgets([ Widgets\AccountWidget::class, Widgets\FilamentInfoWidget::class, ]) ->middleware([ EncryptCookies::class, AddQueuedCookiesToResponse::class, StartSession::class, AuthenticateSession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, SubstituteBindings::class, DisableBladeIconComponents::class, DispatchServingFilamentEvent::class, ]) ->authMiddleware([ Authenticate::class, ]); } public function boot(Panel $panel): void { // }}
Then, you only need to register the plugin to every panel.
use Filament\Panel;use Filament\PanelProvider; class BookingPanelProvider extends PanelProvider{ public function panel(Panel $panel): Panel { return $panel ->id('booking') ->path('booking') ->registration() ->topNavigation() ->discoverResources(in: app_path('Filament/Booking/Resources'), for: 'App\\Filament\\Booking\\Resources') ->discoverPages(in: app_path('Filament/Booking/Pages'), for: 'App\\Filament\\Booking\\Pages') ->discoverWidgets(in: app_path('Filament/Booking/Widgets'), for: 'App\\Filament\\Booking\\Widgets') ->plugin(new CoreSettingsPlugin()); }}
The idea for this approach is from Dan Harrin, author of Filament.
The GitHub repository for this option can be found here.
A few of our Premium Examples: