2 votes

Laravel 5, la jointure à gauche renvoie tous les éléments du côté droit de la jointure

J'ai 3 tables : "items", "faq" et une table de jointure : "item_faq". La table item_faq contient la relation ainsi qu'une colonne order qui permet de classer les faqs par item.

La base de données contient actuellement un total de 5 faqs. La table item_faq contient un total de 9 lignes reliant ces 5 questions à plusieurs articles.

Le contexte est que l'administrateur peut créer/modifier un élément et sélectionner les faq qui seront incluses, ainsi que leur ordre.

Dans la vue de création/modification de l'administrateur de l'article, j'ai besoin d'afficher toutes les FAQ et de pouvoir cocher celles que je veux inclure.

Dans mon contrôleur, je fais une jonction à gauche comme ceci :

$faqs = \App\Faq::leftJoin('item_faq', 'faq.id', '=', 'item_faq.faq_id')->get();

Je suis dd($faqs) pour tester ce qui est retourné et j'obtiens 9 objets. C'est là que se situe mon problème : J'ai besoin qu'il retourne les 5 faqs et s'il y a un item_faq qui est lié à cet item et faq alors la case faq est cochée.

Schéma :

Elément (40+ lignes dans la base de données) : identifiant, autres champs

Faq (il y a 5 lignes existantes dans la base de données) : id, question, réponse, autres champs

item_faq (9 lignes dans la base de données) : champs item_id, faq_id, order, date

L'objet et la FAQ sont tous deux dans un rapport d'interdépendance (many_to_many)

Ce que je veux récupérer

5 faq's et s'il existe une liste item_faq pour l'article et la faq, il cochera cette case.

2voto

João Pinho Points 355

Voyons si j'y parviens : Vous voulez la faq avec leurs articles (si elle existe), n'est-ce pas ? Si c'est ce que vous voulez, vous pouvez utiliser la fonction with méthode comme celle-ci :

$faqs = \App\Faq::with('items')->get();

Dans votre modèle Faq, vous devez avoir une relation avec Item

public method Items() {
    return $this->hasMany(Item::class);
}

Désormais, vous pouvez obtenir des éléments de faqs avec

foreach($faqs as $faq) {
    var_dump($faq->items);
}

MODIFIÉ :

Je pense que vous devez créer une fonction pour vérifier chaque case à cocher et voir si elle doit être cochée comme ceci : Dans votre modèle Faq, créez cette méthode :

public function hasItem($item) {
    return in_array($item, $this->items()->toArray());
}

Dans votre lame pour chaque article, vous vérifiez s'il provient de la FAQ. Comme ceci :

<input type="checkbox" name="items[]" id="{{ $item-id }}" {{ $faq->hasItem($item-id) ? 'checked' : '' }}>

Essayez ceci, s'il vous plaît.

1voto

santosh Points 108

Il semble que plusieurs lignes item_faq aient le même faq_id, c'est pourquoi il joint toutes les lignes item faq avec item_faq.

Seulement s'il y a une relation un à un, vous pouvez obtenir exactement autant de lignes que faq en a.

Si vous souhaitez qu'une dernière question soit renvoyée pour chaque élément, ordonnez par faq_id desc et groupez par item id. renvoie 5 lignes avec la dernière question pour chaque élément.

1voto

Nour Points 1025
DB::table('faq')
->leftjoin('item_faq','faq.id','=','item_faq.faq_id')
->leftjoin('item','item_faq.item','=','item.id')
->select('faq.*','item.id as iId')->get();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X