Relations Un-à-Plusieurs dans Laravel : Maîtrisez hasMany Facilement

Relations Un-à-Plusieurs dans Laravel : Maîtrisez hasMany Facilement



Laravel il y a 4 mois

Tutoriel sur la relation hasMany dans Laravel 

Comprendre hasMany dans Laravel

La relation hasMany dans l'ORM Eloquent de Laravel permet de définir une association un-à-plusieurs entre les modèles. Cela signifie qu'une instance de modèle unique (parent) peut avoir plusieurs modèles associés (enfants). Voici un scénario courant :

  • Modèle parent : Utilisateur
  • Modèle enfant : Article

Un utilisateur peut avoir plusieurs articles associés.

Configuration des modèles

  1. Tables de base de données

    • Assurez-vous d'avoir des tables de base de données distinctes pour les utilisateurs et les articles. La table articles doit généralement avoir une colonne de clé étrangère faisant référence à l'identifiant de l'utilisateur (user_id) dans la table utilisateurs.
  2. Définitions des modèles

    • Créez des classes PHP distinctes pour les modèles Utilisateur et Article, généralement situées dans le répertoire app/Models :

    PHP

    // Utilisateur.php
    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    
    class Utilisateur extends Model
    {
        use HasFactory;
    
        protected $fillable = ['nom', 'email'];
    
        public function articles()
        {
            return $this->hasMany(Article::class);
        }
    }
    
    // Article.php
    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    
    class Article extends Model
    {
        use HasFactory;
    
        protected $fillable = ['titre', 'contenu', 'user_id'];
    
        public function utilisateur()
        {
            return $this->belongsTo(Utilisateur::class);
        }
    }
    
    • La méthode hasMany dans le modèle Utilisateur définit la relation. Elle prend deux arguments :

      • La classe du modèle associé (Article::class)
      • (Facultatif) Le nom de la clé étrangère sur le modèle enfant (par défaut, il s'agit du snake case du nom du modèle parent plus _id, qui est user_id dans ce cas).
    • La méthode belongsTo dans le modèle Article définit la relation inverse, indiquant qu'un article appartient à un seul utilisateur.

Utilisation de la relation hasMany

Maintenant que les relations sont définies, vous pouvez les utiliser dans votre application Laravel :

  1. Récupération des articles d'un utilisateur

    • Trouvez un utilisateur en utilisant Utilisateur::find(1) (remplacez 1 par l'identifiant réel de l'utilisateur).
    • Accédez aux articles de l'utilisateur en utilisant la propriété articles :

    PHP

    $utilisateur = Utilisateur::find(1);
    $articles = $utilisateur->articles;
    
    // Parcourir les articles
    foreach ($articles as $article) {
        echo $article->titre . '<br>';
    }
    
  2. Création d'articles avec un utilisateur

    • Créez une nouvelle instance d'utilisateur.
    • Définissez les attributs de l'utilisateur (nom, email).
    • Créez des articles et associez-les à l'utilisateur en utilisant la méthode de relation articles :

    PHP

    $utilisateur = new Utilisateur;
    $utilisateur->nom = 'Jean Dupont';
    $utilisateur->email = 'jean.dupont@exemple.com';
    
    $article1 = new Article(['titre' => 'Article 1', 'contenu' => 'Ceci est le premier article']);
    $article2 = new Article(['titre' => 'Article 2', 'contenu' => 'Ceci est le second article']);
    
    $utilisateur->articles()->saveMany([$article1, $article2]); // Enregistre les deux articles et les associe à l'utilisateur
    
    // Ou, créez des articles directement dans la méthode save
    $utilisateur->save([
        'articles' => [
            ['titre' => 'Article 1', 'contenu' => 'Ceci est le premier article'],
            ['titre' => 'Article 2', 'contenu' => 'Ceci est le second article'],
        ],
    ]);
    
  3. Considérations supplémentaires

    • Chargement avide (Eager Loading) : Pour récupérer les articles de l'utilisateur en même temps que l'utilisateur
    • Pour récupérer les publications de l'utilisateur avec l'utilisateur en une seule requête, utilisez with lors de la récupération de l'utilisateur :
    • $utilisateur= User::with('articles')->find(1);
      
      Chargement conditionnel avec load
    • La méthode load est particulièrement utile lorsque vous n'avez pas nécessairement besoin de charger les modèles associés dès la récupération du modèle parent. Vous pouvez décider de ne les charger que lorsque cela est nécessaire, ce qui peut améliorer les performances :

      PHP

      $utilisateur = Utilisateur::find(1);
      
      // Vérifiez si les articles n'ont pas encore été chargés
      if (!$utilisateur->relationLoaded('articles')) {
          $utilisateur->load('articles');
      }
      
      // Maintenant, vous pouvez accéder aux articles de l'utilisateur :
      foreach ($utilisateur->articles as $article) {
          echo $article->titre . '<br>';
      }
      

      Chargement de relations spécifiques avec load

      Vous pouvez également spécifier les relations à charger en utilisant un tableau de noms de relations comme arguments de load :

      PHP

      $utilisateur = Utilisateur::find(1);
      $utilisateur->load(['articles', 'commentaires']); // Charger à la fois les articles et les commentaires
      

      Chargement de relations avec des conditions avec load

      Pour un contrôle plus granulaire, vous pouvez passer une closure à la méthode load afin d'appliquer des conditions à la requête du modèle associé :

      PHP

      $utilisateur = Utilisateur::find(1);
      $utilisateur->load(['articles' => function ($query) {
          $query->where('publie', true); // Charger uniquement les articles publiés
      }]);
      
      foreach ($utilisateur->articles as $article) {
          echo $article->titre . '<br>';
      }
      

      loadMissing vs. load

    • Utilisez loadMissing si vous avez déjà récupéré le modèle parent et que vous voulez charger uniquement les relations manquantes :
    • PHP

      $utilisateur = Utilisateur::find(1);
      $utilisateur->loadMissing('articles'); // Charger uniquement les articles s'ils ne sont pas déjà chargés
      

      N'oubliez pas que load et loadMissing exécutent des requêtes distinctes pour récupérer les modèles associés. Si vous savez que vous aurez certainement besoin des modèles associés, envisagez d'utiliser le chargement avide (eager loading) avec with pour de meilleures performances dans une seule requête de base de données. Choisissez l'approche qui convient le mieux à votre cas d'utilisation et à vos besoins en matière de performances.