Lier plusieurs critères

Par Vincent Pieplu, il y a 9 ans


Bonjour,

J'ai créé 5 tables comme ceci :

users (id)
travels (id | name)
criteria (liste de critère, id | name)
criterion_user (table pivot, user_id | criterion_id)
criterion_travel (table pivot, travel_id | criterion_id)
Ce que je dois faire, c'est ressortir les voyages pour l'user 1.

Donc, le cheminement serait de récupérer les criterion_user de l'user 1, puis de récupérer les criterion_travel qui sont identique à ceux de l'user. Pour au final, sortir les travels.

$user = \App\Model\User::with('criteria')->where('id', 1)->first(); $list_criteria = null; foreach($user->criteria as $criterion) { $list_criteria[] = $criterion->name; } if($list_criteria) { $travels = \App\Model\Travel::whereHas('criteria', function($q) use($user, $list_criteria) { $q->whereIn('name', $list_criteria)->whereHas('users', function ($q) use($user) { $q->where('user_id', $user->id); }); })->get(); }

Le souci c'est que le whereIn ne prend pas tous les termes, mais un par un....

Je sèche, merci de votre aide

18 réponses

betaWeb, il y a 9 ans

Salut, de quelle manière sont liés tes models ?

Vincent Pieplu, il y a 9 ans

Je vais faire une petit schéma, ca sera plus clair peut être.

Vincent Pieplu, il y a 9 ans

Sur le schéma, on voit que l'utilisateur 1 a choisi les critères 2 et 11.
Je veux récupérer les voyages (travels) ayant ces mêmes critères.

Donc, ici, je cherche dans criterion_traveloù les criterion_id sont 2 et 11. J'obtiens le travel 4.

Donc, le voyage ressorti devrait être "Voyage : Haïti"

C'est plus clair ?

Merci de ton aide

Metrogeek, il y a 9 ans

Hello Vincent,

Tente ceci :

$user = \App\Model\User::with('criteria')->where('id', 1)->first(); $travels = \App\Model\Travel::has('criteria')->whereHas('criteria', function($query) use ($user) { $query->whereIn('id', $user->criteria->pluck('id')->toArray()); })->groupBy('id', 'ASC')->get();

J'espère que j'ai bien compris ton souci.

Vincent Pieplu, il y a 9 ans

Bonjour,

En fait, c'est bien plus compliqué en fait. Si tu regardes cette exemple :

Mes critères :
Baroudeur (1)
Feru de culture (2)
Amérique du Sud (6)
Asie du Nord Est (8)
Asie du Sud Ouest (10)

Liste des voyages existants :
Voyage : Koweït (1)

  • Baroudeur (1)
  • Asie du Sud Ouest (10)
    Voyage : Réunion (2)
  • Feru de culture (2)
  • Afrique (4)
    Voyage : Grèce (3)
  • Comfy (3)
  • Europe de l'Ouest (12)
    Voyage : Haïti (4)
  • Baroudeur (1)
  • Amérique du Nord (5)
    Voyage : Azerbaïdjan (5)
  • Feru de culture (2)
  • Asie du Sud Ouest (10)
    Voyage : Cameroun (6)
  • Comfy (3)
  • Afrique (4)

Dans ta requête, il me renvoie le voyage à la Réunion, or, dans mes critères, je n'ai pas dit que j'étais intéressé par l'Afrique.

Et c'est là toute la complexité

Metrogeek, il y a 9 ans

Qu'est-ce que te retourne cette partie :

dd($user->criteria->pluck('id')->toArray());
Vincent Pieplu, il y a 9 ans

array:7 [▼
0 => 1
1 => 2
2 => 3
3 => 4
4 => 6
5 => 8
6 => 10
]

Vincent Pieplu, il y a 9 ans

j'ai du enlever le ASC dans le group by car il dit que c'est pas une colonne valide.

Metrogeek, il y a 9 ans

Donc ton user est en pivot sur les critères 1 2 3 4 6 8 10.
Il n'est pas impossible que tu aies des valeurs résiduelles d'un autre test.
Quel est l'id du critère de l'Afrique ?

Edit : oui en effet, le ASC n'avait rien à faire là, j'avais en tête un orderBy par la suite, au temps pour moi.

Vincent Pieplu, il y a 9 ans

Afrique => 4

Metrogeek, il y a 9 ans

Donc quand tu dis : Dans ta requête, il me renvoie le voyage à la Réunion, or, dans mes critères, je n'ai pas dit que j'étais intéressé par l'Afrique.
En réalité, le criètre 4 est bien enregistré sur ton compte, vu que l'id 4 ressort bien du pluck().

Tu vois ce que je veux dire ? Ou c'est moi qui ne saisi toujours pas ton souci ?

Vincent Pieplu, il y a 9 ans

Vu que mes critères de recherches sont
Mes critères :
Baroudeur (1)
Feru de culture (2)
Amérique du Sud (6)
Asie du Nord Est (8)
Asie du Sud Ouest (10)

Je n'ai pas envie de voir un voyage en Afrique.

PS : je viens de découvrir ton site, il est sympa ;)

Vincent Pieplu, il y a 9 ans

J'ai réussi à faire qq choses mais il existe peut etre un procédé plus simple.
Skype pour que je te montre mon écran et en discuter ?

Merci

Metrogeek, il y a 9 ans

De ce que je comprends, si la méthode pluck retourne l'id 4, ça veut dire que la liste de critère que tu viens de me donner est fausse, par rapport à ce que tu as en base de donnée.

A mon avis, si tu requête ta table, tu vas avoir :
Baroudeur (1)
Feru de culture (2)
Afrique (4)
Amérique du Sud (6)
Asie du Nord Est (8)
Asie du Sud Ouest (10)

En lançant :

dd($user->criteria->pluck('name')->toArray());

Tu as quelle liste ? C'est sensé te retourner le nom des critères de l'user, sous forme de tableau.

PS : Merci, ça fait super plaisir !

Vincent Pieplu, il y a 9 ans

array:6 [▼
0 => "Baroudeur"
1 => "Feru de culture"
2 => "Afrique"
3 => "Amérique du Sud"
4 => "Asie du Nord Est"
5 => "Asie du Sud Ouest"
]

Metrogeek, il y a 9 ans
dd(\App\Model\Travel::find(2)->criteria->pluck('id')->toArray());
Vincent Pieplu, il y a 9 ans

Il me ressort :

array:2 [▼
0 => 2
1 => 4
]

Metrogeek, il y a 9 ans

l'id critère 4 est dans les critères de l'user, et du voyage 2 (la réunion).

Du fait que ce voyage fait parti du critère 4, l'user ayant aussi ce critère, ça ressort dans les résultats de la requête. Si tu veux le sortir, il faut que tu supprimes la ligne dans criterion_travel qui contient travel_id 2 criterion_id 4.