Alle Artikel
Laravel4 min

Laravel Filament Tutorial: Admin Panel 2024

Admin Panels gehören zu den zeitaufwendigsten Teilen der Webentwicklung. Laravel Filament ändert das grundlegend. In diesem Laravel Filament Tutorial zeige ich dir, wie du in unter 15 Minuten ein vollständiges, produktionsreifes Admin Panel erstellst – ohne dass du Stunden mit Tabellen-Layouts und CRUD-Operationen verbringen musst.

Was ist Laravel Filament?

Filament ist ein modernes Admin Panel Framework für Laravel, das auf Livewire und Tailwind CSS basiert. Es bietet eine elegante, komponenten-basierte Architektur und folgt Laravel-Konventionen – perfekt für Entwickler, die schnell professionelle Backends erstellen wollen.

Kernfeatures:

  • Automatische CRUD-Generierung aus Eloquent Models
  • Beziehungs-Management (BelongsTo, HasMany, ManyToMany)
  • Formulare mit 40+ Feldtypen
  • Tabellen mit Filtern, Sortierung, Bulk Actions
  • Dashboard mit Widgets
  • Multi-Tenancy Support

Installation und Setup

Starte mit einer frischen Laravel-Installation oder einem bestehenden Projekt:

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

Der Installationsbefehl erstellt automatisch das Admin Panel unter /admin. Migriere deine Datenbank:

php artisan migrate

Erstelle deinen ersten Admin-Benutzer:

php artisan make:filament-user

Das war's – dein Admin Panel ist unter http://dein-projekt.test/admin erreichbar.

Dein erstes Resource erstellen

Das Herzstück dieses Laravel Filament Tutorials: Resources. Sie verbinden deine Eloquent Models mit dem Admin Panel.

Angenommen, du hast ein Product Model:

php artisan make:filament-resource Product

Filament generiert drei Dateien:

  • ProductResource.php – Hauptkonfiguration
  • Pages/ListProducts.php – Listenansicht
  • Pages/CreateProduct.php – Erstellungsformular
  • Pages/EditProduct.php – Bearbeitungsformular

Resource konfigurieren

Öffne app/Filament/Resources/ProductResource.php:

<?php

namespace App\Filament\Resources;

use App\Filament\Resources\ProductResource\Pages;
use App\Models\Product;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;

class ProductResource extends Resource
{
    protected static ?string $model = Product::class;
    protected static ?string $navigationIcon = 'heroicon-o-shopping-bag';
    protected static ?string $navigationGroup = 'Shop';

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\Components\TextInput::make('name')
                    ->required()
                    ->maxLength(255),
                
                Forms\Components\Textarea::make('description')
                    ->rows(3),
                
                Forms\Components\TextInput::make('price')
                    ->numeric()
                    ->prefix('€')
                    ->required(),
                
                Forms\Components\Select::make('category_id')
                    ->relationship('category', 'name')
                    ->searchable()
                    ->preload()
                    ->createOptionForm([
                        Forms\Components\TextInput::make('name')
                            ->required(),
                    ]),
                
                Forms\Components\Toggle::make('is_active')
                    ->default(true),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('name')
                    ->searchable()
                    ->sortable(),
                
                Tables\Columns\TextColumn::make('category.name')
                    ->badge(),
                
                Tables\Columns\TextColumn::make('price')
                    ->money('EUR')
                    ->sortable(),
                
                Tables\Columns\IconColumn::make('is_active')
                    ->boolean(),
                
                Tables\Columns\TextColumn::make('created_at')
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                Tables\Filters\SelectFilter::make('category')
                    ->relationship('category', 'name'),
                
                Tables\Filters\TernaryFilter::make('is_active')
                    ->label('Status')
                    ->boolean()
                    ->trueLabel('Aktiv')
                    ->falseLabel('Inaktiv'),
            ])
            ->actions([
                Tables\Actions\EditAction::make(),
                Tables\Actions\DeleteAction::make(),
            ])
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                ]),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListProducts::route('/'),
            'create' => Pages\CreateProduct::route('/create'),
            'edit' => Pages\EditProduct::route('/{record}/edit'),
        ];
    }
}

Beziehungen verwalten

Ein praktisches Beispiel für One-to-Many-Beziehungen. Füge in deinem CategoryResource eine Relation Manager hinzu:

php artisan make:filament-relation-manager CategoryResource products name

In app/Filament/Resources/CategoryResource.php:

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

Der generierte Relation Manager zeigt alle Produkte einer Kategorie direkt im Edit-Formular.

Dashboard und Widgets

Dashboards machen dein Admin Panel lebendig. Erstelle ein Stats-Widget:

php artisan make:filament-widget StatsOverview --stats

In app/Filament/Widgets/StatsOverview.php:

<?php

namespace App\Filament\Widgets;

use App\Models\Product;
use App\Models\Order;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;

class StatsOverview extends BaseWidget
{
    protected function getStats(): array
    {
        return [
            Stat::make('Produkte', Product::count())
                ->description('Aktive Produkte')
                ->descriptionIcon('heroicon-m-shopping-bag')
                ->color('success'),
            
            Stat::make('Bestellungen', Order::count())
                ->description('Diesen Monat')
                ->descriptionIcon('heroicon-m-arrow-trending-up')
                ->color('primary'),
            
            Stat::make('Umsatz', '€' . number_format(Order::sum('total'), 2))
                ->description('Gesamt')
                ->descriptionIcon('heroicon-m-currency-euro')
                ->color('warning'),
        ];
    }
}

Benutzer und Rollen

Filament unterstützt Laravel's Gate/Policy-System nativ. Erstelle eine Policy:

php artisan make:policy ProductPolicy --model=Product

In ProductPolicy.php:

public function viewAny(User $user): bool
{
    return $user->hasRole('admin') || $user->hasRole('editor');
}

public function create(User $user): bool
{
    return $user->hasRole('admin');
}

public function update(User $user, Product $product): bool
{
    return $user->hasRole('admin') || 
           ($user->hasRole('editor') && $product->user_id === $user->id);
}

Filament respektiert diese Policies automatisch – keine Extra-Konfiguration nötig.

Best Practices aus der Praxis

1. Navigation gruppieren Halte dein Menü übersichtlich:

protected static ?string $navigationGroup = 'Shop-Verwaltung';
protected static ?int $navigationSort = 2;

2. Eloquent Eager Loading Vermeide N+1 Queries:

public static function getEloquentQuery(): Builder
{
    return parent::getEloquentQuery()
        ->with(['category', 'user']);
}

3. Custom Actions Erweitere Tabellen mit eigenen Aktionen:

Tables\Actions\Action::make('duplicate')
    ->icon('heroicon-o-document-duplicate')
    ->action(fn (Product $record) => $record->replicate()->save())

4. Validierung Nutze Laravel's Validation:

Forms\Components\TextInput::make('slug')
    ->unique(ignoreRecord: true)
    ->rules(['alpha_dash'])

Performance-Tipps

Für große Datenmengen:

// Simple Pagination aktivieren
protected static bool $shouldSkipAuthorization = false;

// Chunk-Loading für Exporte
public static function getEloquentQuery(): Builder
{
    return parent::getEloquentQuery()
        ->withoutGlobalScopes();
}

Fazit

Dieses Laravel Filament Tutorial hat dir gezeigt, wie schnell du moderne Admin Panels entwickelst. Filament kombiniert Laravel-Best-Practices mit einer intuitiven API – perfekt für Projekte, bei denen du dich auf Business-Logik statt UI-Boilerplate konzentrieren willst.

Die wichtigsten Punkte:

  • Installation in 2 Minuten
  • Automatische CRUD-Generierung
  • Eloquent-Integration ohne Kompromisse
  • Production-ready mit Policies und Validierung

Du arbeitest an einem Laravel-Projekt mit komplexem Backend? Ich helfe dir gerne bei der Implementierung von Filament oder individuellen Admin-Lösungen.

Laravel Filament TutorialLaravelFreelancerWebentwicklungDüsseldorf