Relations HasMany/BelongsTo dans Laravel 12 : Matérialiser une relation entre modèles
Bienvenue dans ce septième épisode de notre série sur Laravel 12 ! 🚀 Aujourd'hui, nous allons apprendre à concrétiser une relation entre modèles avec notre première relation HasMany/BelongsTo.
Introduction
Dans notre épisode précédent, nous avons découvert les bases d'Eloquent, l'ORM de Laravel. Maintenant, nous allons voir comment établir des relations concrètes entre nos modèles pour qu'ils interagissent ensemble de manière cohérente.
📌 Au programme :
- ✅ Utiliser Tinker efficacement
- ✅ Créer des clés étrangères proprement
- ✅ Comprendre et implémenter la relation HasMany
- ✅ Comprendre et implémenter la relation BelongsTo
- ✅ Tester et manipuler nos relations
Définir notre relation
Pour notre exemple, nous allons créer une relation entre nos recettes et les utilisateurs. En termes plus grammaticaux :
- Un utilisateur possède zéro, une ou plusieurs recettes
- Une recette appartient à un utilisateur (ou pas, si nullable)
Cette relation est ce qu'on appelle une relation "one-to-many" ou dans Laravel, une relation HasMany/BelongsTo.
Visualiser notre base de données
Avant de commencer à modifier notre structure, explorons nos tables actuelles. Laravel propose des commandes pratiques pour visualiser notre base de données directement dans le terminal :
php artisan db:show
Cette commande nous montre toutes les informations concernant notre base de données : le driver (SQLite), la connexion, le chemin du fichier et le schéma de nos tables.
Pour voir le détail d'une table spécifique :
php artisan db:table recipes
Cette commande affiche la structure de la table avec ses colonnes, types et contraintes.
Créer une migration pour notre clé étrangère
Pour établir notre relation, nous devons ajouter une clé étrangère user_id
dans notre table recipes
. Créons une migration :
php artisan make:migration add_user_id_to_recipes
Dans cette migration, nous allons ajouter notre colonne user_id
:
public function up()
{
Schema::table('recipes', function (Blueprint $table) {
$table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
});
}
public function down()
{
Schema::table('recipes', function (Blueprint $table) {
$table->dropForeign(['user_id']);
$table->dropColumn('user_id');
});
}
Expliquons les différentes parties :
foreignId('user_id')
: crée une colonne de type entier non signénullable()
: rend la colonne nullable (une recette peut ne pas appartenir à un utilisateur)constrained()
: ajoute la contrainte d'intégrité référentielle vers la tableusers
nullOnDelete()
: met à NULL leuser_id
si l'utilisateur est supprimé
Note importante: L'ordre des méthodes est crucial ! Mettez toujours
nullable()
avantconstrained()
sinon vous risquez des erreurs car vous ne pouvez pas ajouter une colonne non nullable sans valeur par défaut.
Méthode plus verbeuse (ancienne approche)
Avant Laravel proposait cette syntaxe plus verbeuse :
$table->unsignedBigInteger('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('users')->nullOnDelete();
C'est important de comprendre les deux approches, mais la nouvelle méthode est beaucoup plus concise.
Définir nos relations dans les modèles
Une fois notre migration exécutée (php artisan migrate
), nous devons définir les relations dans nos modèles.
Dans le modèle User
use Illuminate\Database\Eloquent\Relations\HasMany;
public function recipes(): HasMany
{
return $this->hasMany(Recipe::class);
}
Dans le modèle Recipe
use Illuminate\Database\Eloquent\Relations\BelongsTo;
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
Pour éviter de retourner null
quand une recette n'a pas d'utilisateur, on peut utiliser withDefault
:
public function user(): BelongsTo
{
return $this->belongsTo(User::class)->withDefault([
'name' => 'Inconnu'
]);
}
Utiliser Tinker pour tester nos relations
Tinker est un outil puissant pour interagir avec notre application Laravel directement depuis le terminal :
php artisan tinker
Avant de tester, assurons-nous d'avoir des utilisateurs :
// Dans DatabaseSeeder.php
\App\Models\User::factory(10)->create();
// Puis en terminal
php artisan db:seed
Maintenant, utilisons Tinker pour lier une recette à un utilisateur :
// Récupérer une recette
$recipe = \App\Models\Recipe::first();
// Mettre à jour le user_id
\App\Models\Recipe::where('id', 1)->update(['user_id' => 1]);
// Rafraîchir notre modèle
$recipe->refresh();
// Vérifier la relation
$recipe->user; // Affiche l'utilisateur lié
// Récupérer les recettes d'un utilisateur
$user = \App\Models\User::first();
$user->recipes; // Affiche une collection de recettes
Tester la fonctionnalité withDefault
$recipe = \App\Models\Recipe::where('id', 2)->first();
$recipe->user; // Retourne notre valeur par défaut "Inconnu" si aucun utilisateur n'est lié
Conclusion
Les relations HasMany et BelongsTo sont fondamentales dans Laravel. Elles nous permettent de:
- Créer des structures de données cohérentes
- Accéder facilement aux données liées (
$user->recipes
ou$recipe->user
) - Maintenir l'intégrité de nos données grâce aux contraintes
Dans notre prochain épisode, nous explorerons d'autres types de relations comme ManyToMany et les fonctionnalités avancées d'Eloquent.
Vidéos de la playlist
Premiers pas et structure de Laravel 12
Les vues avec Blade et TailwindCSS
Passer des données aux vues
Le M dans MVC
Les migrations dans Laravel 12
Eloquent dans Laravel 12
Relations HasMany/BelongsTo dans Laravel 12
Réservez une session de mentorat personnalisée pour accélérer votre apprentissage et résoudre vos problèmes techniques.
Réserver une session de mentorat