Rapid Admin Panels with FilamentPHP

· 4 min read

Filament has revolutionized how we build admin interfaces in Laravel. Built on the TALL stack (Tailwind, Alpine, Laravel, Livewire), it offers an incredible developer experience for creating beautiful, responsive admin panels.

Installation

composer require filament/filament:"^3.2" -W
php artisan filament:install --panels

This creates a new user and sets up the admin panel at /admin.

Creating a Resource

Resources are the core of Filament. They map to your Eloquent models.

php artisan make:filament-resource Post

This generates:

  • app/Filament/Resources/PostResource.php
  • app/Filament/Resources/PostResource/Pages/ListPosts.php
  • app/Filament/Resources/PostResource/Pages/CreatePost.php
  • app/Filament/Resources/PostResource/Pages/EditPost.php

Configuring the Form

Define your input fields in form():

use Filament\Forms;
use Filament\Forms\Form;

public static function form(Form $form): Form
{
    return $form
        ->schema([
            Forms\Components\TextInput::make('title')
                ->required()
                ->maxLength(255),
            
            Forms\Components\Str::make('slug')
                ->required(),

            Forms\Components\Select::make('author_id')
                ->relationship('author', 'name')
                ->searchable()
                ->preload(),

            Forms\Components\RichEditor::make('content')
                ->columnSpanFull(),
            
            Forms\Components\Toggle::make('is_published'),
            
            Forms\Components\DateTimePicker::make('published_at'),
        ]);
}

Configuring the Table

Define your data table in table():

use Filament\Tables;
use Filament\Tables\Table;

public static function table(Table $table): Table
{
    return $table
        ->columns([
            Tables\Columns\TextColumn::make('title')
                ->searchable()
                ->sortable(),
            
            Tables\Columns\TextColumn::make('author.name')
                ->label('Author')
                ->sortable(),

            Tables\Columns\IconColumn::make('is_published')
                ->boolean(),

            Tables\Columns\TextColumn::make('created_at')
                ->dateTime()
                ->sortable(),
        ])
        ->filters([
            Tables\Filters\SelectFilter::make('author')
                ->relationship('author', 'name'),
                
            Tables\Filters\TernaryFilter::make('is_published'),
        ])
        ->actions([
            Tables\Actions\EditAction::make(),
            Tables\Actions\DeleteAction::make(),
        ])
        ->bulkActions([
            Tables\Actions\BulkActionGroup::make([
                Tables\Actions\DeleteBulkAction::make(),
            ]),
        ]);
}

Relationships

Filament handles relationships elegantly.

BelongsTo

Used in forms via Select component and tables via dot notation author.name.

HasMany (Relation Managers)

To manage comments on a post, generate a relation manager:

php artisan make:filament-relation-manager PostResource comments title

Register it in PostResource:

public static function getRelations(): array
{
    return [
        RelationManagers\CommentsRelationManager::class,
    ];
}

Custom Widgets

Create a stats dashboard:

php artisan make:filament-widget BlogStatsOverview --stats-overview
// app/Filament/Widgets/BlogStatsOverview.php
protected function getStats(): array
{
    return [
        Stat::make('Total Posts', Post::count()),
        Stat::make('Published Posts', Post::where('is_published', true)->count()),
        Stat::make('Pending Reviews', Post::where('is_published', false)->count()),
    ];
}

Actions

Custom actions allow you to execute logic directly from the table or form.

Tables\Actions\Action::make('publish')
    ->action(function (Post $record) {
        $record->update(['is_published' => true]);
    })
    ->requiresConfirmation()
    ->color('success')
    ->icon('heroicon-o-check');

Enable global search for your resource:

protected static ?string $recordTitleAttribute = 'title';

public static function getGlobalSearchResultDetails(Model $record): array
{
    return [
        'Author' => $record->author->name,
    ];
}

Validations & Hooks

You can hook into the lifecycle of resource pages.

// app/Filament/Resources/PostResource/Pages/CreatePost.php

protected function mutateFormDataBeforeCreate(array $data): array
{
    $data['user_id'] = auth()->id();
    return $data;
}

protected function afterCreate(): void
{
    // Send notification
}

Customizing the Look

Publish configuration to change colors, logo, and simpler settings:

// app/Providers/Filament/AdminPanelProvider.php
public function panel(Panel $panel): Panel
{
    return $panel
        ->default()
        ->id('admin')
        ->path('admin')
        ->colors([
            'primary' => Color::Amber,
        ])
        ->brandLogo(asset('images/logo.png'));
}

Best Practices

  1. Keep logic in Models - Don't bloat Resources with business logic
  2. Use Policies - Filament respects standard Laravel policies for authorization
  3. Optimize Queries - Use eagerLoad in table queries to prevent N+1
  4. Custom Fields - Create custom blade components for specialized inputs
  5. Testing - Use Livewire testing helpers to test interactions

Summary

Filament removes the drudgery of building admin panels. It allows you to:

  • Generate CRUD interfaces instantly
  • Manage complex relationships easily
  • Create custom dashboards and widgets
  • Extend functionality with the TALL stack

It's currently the best choice for Laravel administrative interfaces.

Comments