Routing & Controllers
Thème :
Junior
1 vues ·3/9 leçons

Plongée au cœur du Route Model Binding (Liaison Modèle-Route)

La liaison modèle-route (Route Model Binding) injecte automatiquement des instances de vos modèles directement dans vos routes ou vos contrôleurs. Au lieu de faire manuellement une requête à la base de données, Laravel s’en occupe pour vous.

Liaison Implicite (Implicit Binding)

Laravel résout automatiquement les modèles Eloquent en faisant correspondre le nom de la variable avec le segment de la route :

// Définition de la route
Route::get('/users/{user}', function (User $user) {
    return $user;
});

// Lorsqu'on visite /users/1 :
// 1. Laravel voit {user} dans la route
// 2. Voit le type-hint `User $user` dans la fonction
// 3. Exécute automatiquement `User::findOrFail(1)`
// 4. Injecte l'instance `User` trouvée directement dans votre fonction

Dans les Contrôleurs

// routes/web.php
Route::get('/posts/{post}', [PostController::class, 'show']);

// app/Http/Controllers/PostController.php
class PostController extends Controller
{
    public function show(Post $post)  // Résolu automatiquement !
    {
        return view('posts.show', ['post' => $post]);
    }
}

Personnaliser la Clé de Recherche

Par défaut, les modèles sont recherchés par leur clé primaire (l’ID). Pour utiliser une autre colonne :

// Dans la route
Route::get('/posts/{post:slug}', function (Post $post) {
    return $post;
});
// /posts/mon-premier-article → recherche par la colonne slug

// Ou dans le modèle
class Post extends Model
{
    /**
     * Obtenir le nom de la clé de route pour le modèle.
     */
    public function getRouteKeyName(): string
    {
        return 'slug';
    }
}
// Désormais, {post} sera toujours résolu via la colonne slug

Liaisons Ciblées (Scoped Bindings)

Assurez-vous que les modèles enfants appartiennent bien aux modèles parents :

Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    return $post;
});

// Sans scoping : /users/1/posts/5 retournerait l'article 5 même s'il appartient à l'utilisateur 2
// Avec scoping : Retourne une erreur 404 si l'article n'appartient pas à l'utilisateur

Activer le scoping :

// Méthode 1 : Utiliser scopeBindings()
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    return $post;
})->scopeBindings();

// Méthode 2 : Dans un groupe de routes
Route::scopeBindings()->group(function () {
    Route::get('/users/{user}/posts/{post}', ...);
});

Ceci nécessite que la relation posts() existe sur le modèle User :

class User extends Model
{
    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}

Liaison Explicite (Explicit Binding)

Personnalisez comment les modèles sont résolus dans AppServiceProvider :

use App\Models\User;
use Illuminate\Support\Facades\Route;

public function boot(): void
{
    // Logique de résolution personnalisée
    Route::bind('user', function (string $value) {
        return User::where('name', $value)->firstOrFail();
    });
}

// Désormais, {user} se résout par le nom au lieu de l'ID

Logique de Résolution Personnalisée dans les Modèles

Remplacer la façon dont un modèle résout la liaison de route :

class User extends Model
{
    /**
     * Récupérer le modèle correspondant à une valeur liée.
     */
    public function resolveRouteBinding($value, $field = null): ?Model
    {
        // Logique personnalisée : inclure les éléments supprimés (soft-deleted) pour les admins
        return $this->where($field ?? 'id', $value)
                    ->when(auth()->user()?->isAdmin(), fn ($q) => $q->withTrashed())
                    ->firstOrFail();
    }
}

Gérer les Modèles Introuvables

Par défaut, si un modèle n’est pas trouvé, Laravel retourne une erreur 404. Vous pouvez personnaliser cela :

Route::get('/users/{user}', function (User $user) {
    return $user;
})->missing(function (Request $request) {
    return redirect()->route('users.index')
        ->with('error', 'Utilisateur introuvable');
});

Modèles Supprimés (Soft Deleted Models)

Inclure les modèles supprimés de façon logicielle (soft-deleted) :

Route::get('/users/{user}', function (User $user) {
    return $user;
})->withTrashed();  // Inclure les utilisateurs supprimés (soft-deleted)

Liaison d’Enum (Enum Binding)

Les Enums adossés (backed enums) de PHP 8.1+ fonctionnent avec la liaison de route :

// Définir un Enum
enum Category: string
{
    case Fruits = 'fruits';
    case Vegetables = 'legumes';
}

// Utiliser dans une route
Route::get('/categories/{category}', function (Category $category) {
    return $category->value;
});
// /categories/fruits → 'fruits'
// /categories/invalide → Erreur 404

Bonnes Pratiques

// ✅ Bien : Utiliser le Route Model Binding
Route::get('/users/{user}', function (User $user) {
    return $user;
});

// ❌ À Éviter : Recherche manuelle
Route::get('/users/{id}', function ($id) {
    $user = User::findOrFail($id);  // Inutile
    return $user;
});

// ✅ Bien : Lier (Scoper) les ressources imbriquées
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
})->scopeBindings();

Ressources


📘 Cette leçon fait partie du cours Routage & Contrôleurs Laravel sur la plateforme d’apprentissage RostoDev.

Prêt à passer à la suite ?

Vous avez terminé cette leçon sur Plongée au cœur du Route Model Binding (Liaison Modèle-Route). Continuez votre apprentissage avec la prochaine leçon ou explorez d'autres formations.