Créer un Système de Réservation avec Laravel Filament

December 28, 2025 Premium

Développez une application complète de gestion de réservations pour hôtels et locations saisonnières : propriétés, chambres, clients, calcul automatique des prix et tableau de bord avec statistiques en temps réel.

Créer un Système de Réservation avec Laravel Filament

Apprenez à créer une application de gestion de réservations pour hôtels, appartements et locations saisonnières avec Laravel et FilamentPHP. Ce guide vous accompagne pour mettre en place un système complet avec propriétés, chambres, clients et réservations, ainsi qu'un tableau de bord avec statistiques en temps réel.

Prérequis

Avant de commencer, assurez-vous d'avoir :

  • Une application Laravel installée
  • FilamentPHP v4 configuré
  • Le package Laravel Trend pour les graphiques

Installation des dépendances

composer require flowframe/laravel-trend

Création des Modèles et Migrations

1. Propriétés (Hôtels, Appartements, etc.)

php artisan make:model Property -m

Dans la migration :

$table->string('name');
$table->enum('type', ['hotel', 'apartment', 'house', 'villa', 'cabin'])->default('hotel');
$table->text('description')->nullable();
$table->string('address')->nullable();
$table->string('city')->nullable();
$table->string('country')->nullable();
$table->string('postal_code')->nullable();
$table->string('phone')->nullable();
$table->string('email')->nullable();
$table->string('image')->nullable();
$table->boolean('is_active')->default(true);

2. Chambres

php artisan make:model Room -m

Dans la migration :

$table->foreignId('property_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->text('description')->nullable();
$table->integer('capacity')->default(2);
$table->integer('beds')->default(1);
$table->decimal('price_per_night', 10, 2);
$table->string('image')->nullable();
$table->boolean('is_available')->default(true);

3. Clients

php artisan make:model Guest -m

Dans la migration :

$table->string('first_name');
$table->string('last_name');
$table->string('email')->unique();
$table->string('phone')->nullable();
$table->string('address')->nullable();
$table->string('city')->nullable();
$table->string('country')->nullable();
$table->text('notes')->nullable();

4. Réservations

php artisan make:model Booking -m

Dans la migration :

$table->foreignId('room_id')->constrained()->cascadeOnDelete();
$table->foreignId('guest_id')->constrained()->cascadeOnDelete();
$table->date('check_in');
$table->date('check_out');
$table->integer('guests_count')->default(1);
$table->decimal('total_price', 10, 2);
$table->enum('status', ['pending', 'confirmed', 'cancelled', 'completed'])->default('pending');
$table->text('notes')->nullable();

Modèle Room avec Vérification de Disponibilité

La logique clé de l'application est la vérification de disponibilité des chambres :

class Room extends Model
{
    public function isAvailableForDates(string $checkIn, string $checkOut, ?int $excludeBookingId = null): bool
    {
        $query = $this->bookings()
            ->whereNotIn('status', ['cancelled'])
            ->where(function ($q) use ($checkIn, $checkOut) {
                $q->whereBetween('check_in', [$checkIn, $checkOut])
                    ->orWhereBetween('check_out', [$checkIn, $checkOut])
                    ->orWhere(function ($q2) use ($checkIn, $checkOut) {
                        $q2->where('check_in', '<=', $checkIn)
                            ->where('check_out', '>=', $checkOut);
                    });
            });

        if ($excludeBookingId) {
            $query->where('id', '!=', $excludeBookingId);
        }

        return !$query->exists();
    }
}

Modèle Booking avec Statuts

class Booking extends Model
{
    public function getNightsCountAttribute(): int
    {
        return Carbon::parse($this->check_in)->diffInDays(Carbon::parse($this->check_out));
    }

    public static function getStatuses(): array
    {
        return [
            'pending' => 'En attente',
            'confirmed' => 'Confirmée',
            'cancelled' => 'Annulée',
            'completed' => 'Terminée',
        ];
    }

    public static function getStatusColor(string $status): string
    {
        return match ($status) {
            'pending' => 'warning',
            'confirmed' => 'success',
            'cancelled' => 'danger',
            'completed' => 'gray',
            default => 'primary',
        };
    }
}

Formulaire de Réservation avec Calcul Automatique

Le formulaire Filament calcule automatiquement le prix total :

class BookingForm
{
    public static function calculateTotal(Get $get, Set $set): void
    {
        $roomId = $get('room_id');
        $checkIn = $get('check_in');
        $checkOut = $get('check_out');

        if (!$roomId || !$checkIn || !$checkOut) {
            return;
        }

        $room = Room::find($roomId);
        if (!$room) {
            return;
        }

        $nights = Carbon::parse($checkIn)->diffInDays(Carbon::parse($checkOut));
        $total = $nights * $room->price_per_night;

        $set('total_price', $total);
    }
}

Les champs utilisent ->live() et ->afterStateUpdated() pour déclencher le calcul :

DatePicker::make('check_in')
    ->label('Date d\'arrivée')
    ->required()
    ->live()
    ->afterStateUpdated(fn (Get $get, Set $set) => self::calculateTotal($get, $set)),

Widget Statistiques du Dashboard

Créez un widget pour afficher les KPIs :

php artisan make:filament-widget StatsOverview --stats-overview
class StatsOverview extends StatsOverviewWidget
{
    protected function getStats(): array
    {
        $todayBookings = Booking::whereDate('check_in', today())->count();
        $pendingBookings = Booking::where('status', 'pending')->count();
        $monthRevenue = Booking::whereMonth('created_at', now()->month)
            ->whereYear('created_at', now()->year)
            ->whereIn('status', ['confirmed', 'completed'])
            ->sum('total_price');

        return [
            Stat::make('Arrivées du jour', $todayBookings)
                ->description('Check-in aujourd\'hui')
                ->color('success'),
            Stat::make('Réservations en attente', $pendingBookings)
                ->description('À confirmer')
                ->color('warning'),
            Stat::make('Revenus du mois', number_format($monthRevenue, 2, ',', ' ') . ' €')
                ->description('Réservations confirmées')
                ->color('primary'),
        ];
    }
}

Widget Graphique des Réservations

Utilisez Laravel Trend pour visualiser les tendances :

php artisan make:filament-widget BookingsChart --chart
class BookingsChart extends ChartWidget
{
    protected ?string $heading = 'Réservations des 30 derniers jours';

    protected function getData(): array
    {
        $data = Trend::model(Booking::class)
            ->between(
                start: now()->subDays(30),
                end: now(),
            )
            ->perDay()
            ->count();

        return [
            'datasets' => [
                [
                    'label' => 'Réservations',
                    'data' => $data->map(fn (TrendValue $value) => $value->aggregate),
                ],
            ],
            'labels' => $data->map(fn (TrendValue $value) => Carbon::parse($value->date)->format('d/m')),
        ];
    }

    protected function getType(): string
    {
        return 'bar';
    }
}

Resources Filament

Générez les Resources pour chaque modèle :

php artisan make:filament-resource Property
php artisan make:filament-resource Room
php artisan make:filament-resource Guest
php artisan make:filament-resource Booking

Conclusion

En quelques étapes, vous avez une application complète de gestion de réservations qui :

  • Gère plusieurs types de propriétés (hôtels, appartements, villas...)
  • Organise les chambres avec tarification par nuit
  • Maintient une base de données clients
  • Vérifie automatiquement la disponibilité des chambres
  • Calcule le prix total en temps réel
  • Affiche un tableau de bord avec statistiques et graphiques

Cette architecture est facilement extensible pour ajouter des fonctionnalités comme les paiements en ligne, les notifications par email, ou un calendrier de disponibilité.

Obtenez le Code Source Complet

Gagnez du temps et accédez à l'intégralité du projet.

Je veux le code source