Exemple d'un blogue avec des articles et des commentaires. Un article peut avoir plusieurs commentaires et un commentaire appartient à un seul article.
Les relations se configurent dans les fichiers modèles avec les méthodes hasMany et belongsTo.
Afin de respecter les conventions de Laravel, dans la tables comments
, il doit y avoir une colonne post_id
qui contient l'id de l'article auquel appartient le commentaire.
Fichier modèle Post.php
class Post extends Model { public function comments() { return $this->hasMany(Comment::class); } }
Fichier modèle Comment.php
class Comment extends Model { public function post() { return $this->belongsTo(Post::class); } }
Exemple d'un blogue avec des articles et des catégories. un article peut avoir plusieurs catégories et une catégorie peut avoir plusieurs articles.
On a donc deux tables:
Il faut créer une table pivot. Afin de respecter les conventions de Laravel, la table doit prendre le nom au singulier des deux tables qu'elle va lier et on les sépare par un trait d'union.
On met les noms des tables dans l'ordre alphabétique. La table pivot se nommera donc:
Dans les fichiers de modèles, on ajoute la méthode belongsToMany()
Fichier modèle Post.php
class Post extends Model { public function categories() { return $this->belongsToMany(Category::class); } }
Fichier modèle Category.php
class Category extends Model { public function posts() { return $this->belongsToMany(Post::class); } }
Maintenant que la relation est en place, quand on demandera dans un contrôleur d'aller chercher un article, le modèle prendra automatiquement les catégories associées.
Exemple
$posts = Post::find(1); dd($posts->categories);
Cela affichera
Pour enregistrer les informations dans la table category_post
Exemples
$post->categories()->sync(request()->get('categories')); // request()->get('categories') contient un tableau avec les id des catégories à enregistrer //Autres exemples $post->categories()->attach([1,2,3]); // Maintenant l'article a les catégories 1,2,3 $post->categories()->detach([2]); // Maintenant l'article a les catégories 1,3 $post->categories()->sync([1,2]); // Maintenant l'article a les catégories 1,2 $post->categories()->syncWithoutDetaching([1,2]); // Ne détache pas l'id 3 par rapport à l'exemple précédent
Afin de retrouver les informations facilement dans la table pivot, on utilise l'attribut pivot.
Exemple pour le TP sur les images, dans le modèle Image.php, on peut écrire la relation comme ceci:
public function users() { return $this->belongsToMany(User::class)->withPivot('alert'); }
On ajoute la colonne alert
en tant que pivot
Voici ce que l'on peut faire dans le contrôleur maintenant:
// On cherche toutes les images qui ont l'id = 1 comme location $images = Location::find(1)->images()->get(); // On obient une ou plusieurs images. on fait une boucle Foreach afin de traiter chaque image foreach ($images as $image) { // Pour chaque image, on teste si la colonne alert = 1, si oui, on affiche les informations de $image echo $image->users->where('pivot.alert', 1); // On peut aussi compter combien de fois une image à un alert = 1 echo $image->users->where('pivot.alert', 1)->count() }
(j'ai mis des echo
dans le contrôleur pour l'exemple mais bien sûr, on n'en met jamais à cet endroit !)
Exemple d'une méthode search()
dans un contrôleur.
On utilise une méthode getReportedImage()
afin d'ajouter l'attribut approved
à l'objet image. Cet attribut prendra la valeur 0 ou 1 suivant si l'image à deux alertes ou plus ou si l'image ou moins de deux alertes.
public function search(Request $request) { if ($request->get('search') == "") return redirect('/'); $id_location = Location::where('name', 'like', $request->get('search'))->first(); if (is_null($id_location)) return redirect('/')->with('ok', __ ("Aucun résultat trouvé")); $images = Location::find($id_location->id)->images(); $images = $this->getReportedImage($images)->where('approved', 1); return view('home', compact('images')); } public function getReportedImage($images) { $images->transform(function($image) { $number = $image->users->where('pivot.alert', 1)->count(); $image->approved = ($number >= 2) ? 0 : 1; return $image; }); return $images; }
Dans une vue Blade, on peut utiliser:
{{ $image->users->where('pivot.alert', 1)->count() }}