J'apprends Laravel et Laravel éloquents pour le moment et maintenant j'essaye de résoudre un problème en utilisant les relations dans Laravel. Voici ce que je veux archiver:
La base de données contient de nombreux clubs sportifs. Un club de sport a beaucoup d'équipes. Chaque équipe a des jeux. La table des équipes a une colonne nommée club_id
. Maintenant, je veux créer des relations éloquentes pour obtenir tous les jeux d'un club.
Voici ce que j'ai obtenu jusqu'à présent:
Modèle de club
id => PRIMAIRE
public function games() { return $this->hasManyThrough('App\Models\Game','App\Models\Team','club_id','home_id'); }
Modèle de jeu
home_id = > FOREIGN KEY de l'équipe; guest_id => FOREIGN KEY de l'équipe
public function homeTeam() { return $this->belongsTo('App\Models\Team','home_id')->where('club_id','=', $club_id); } public function guestTeam() { return $this->belongsTo('App\Models\Team','guest_id')->where('club_id','=', $club_id); }
Modèle d'équipe
id => PRIMARY; club_id => FOREIGN
Dans mon contrôleur, tout ce que je veux faire est Club::findOrFail($id)->games()
L'exécution du code ci-dessus renvoie une erreur SQL indiquant que la table de jeux n'a pas de colonne nommée club_id
.
Quelle est la bonne façon de créer ce type de relation?
Merci!
MODIFIER
Grâce à Nikola Gavric, j'ai trouvé un moyen d'obtenir tous les jeux - mais uniquement lorsque les équipes du club sont l'équipe à domicile ou à l'extérieur.
Voici la relation:
public function games() { return $this->hasMany('App\Models\Games')->whereHas('homeTeam')->orWhereHas('guestTeam'); }
3 Réponses :
Lorsque vous définissez ce club aMany
jeux, vous indiquez que le jeu a une clé étrangère appelée club_id
pointant vers Club. appartient à
est le même mais dans l'autre sens. Celles-ci doivent être cohérentes avec ce que vous avez sur votre base de données, ce qui signifie que vous devez avoir défini ces clés comme des clés étrangères sur vos tables.
La table de jeux n'a que la maison et l'équipe invitée comme clés étrangères qui pointent vers l'équipe. L'équipe a une clé étrangère appelée club_id qui pointe vers club
Lorsque vous dites $ this-> hasMany ('App \ Models \ Games')
sur la fonction de jeux de la classe Club, vous indiquez que Game
a un club_id
, c'est pourquoi "un club a beaucoup de jeux".
Essayez ceci ...
Modèle de club
Club::where('id',$id)->has('games.guestTeam')->get();
Modèle de jeu
public function homeTeam() { return $this->belongsTo('App\Models\Team','home_id'); } public function guestTeam() { return $this->belongsTo('App\Models\Team','guest_id'); }
Votre requête comme
public function games() { return $this->hasMany('App\Models\Games'); }
Il existe une méthode pour récupérer une "relation distante avec un intermédiaire" et elle s'appelle A plusieurs travers .
Il existe également un exemple concret sur la façon de l'utiliser, qui inclut Post
, Country
et User
, mais je pense que ce sera suffisant pour vous donner un indice sur la façon de créer une relation jeux
à l'intérieur d'un modèle Club
. Voici un lien, mais lorsque vous ouvrez-le, recherchez le mot-clé hasManyThrough
et vous verrez un exemple.
PS: Avec les bonnes clés de nommage
, vous pouvez y parvenir avec: p >
$merged->sortBy(function($game, $key) { return $game->created_at; });
Puisque vous avez 2 types d'équipes, vous pouvez créer 2 relations différentes où chaque relation vous donnera une du type que vous avoir besoin. Comme ceci:
$gamesHome = $model->gamesAsHome; $gamesGuests = $model->gamesAsGuests; $games = $gamesHome->merge($gamesGuests); return $games->unique()->all();
Fusion des relations : pour fusionner ces 2 relations, vous pouvez utiliser merge ()
sur la méthode Collection
, il ajoutera tous les enregistrements de la deuxième collection dans le premier .
public function gamesAsHome() { return $this ->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'home_id'); } public function gamesAsGuests() { return $this ->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'guest_id'); }
Je l'ai presque compris! J'utilise ceci ici en ce moment: return $ this-> hasManyThrough ('App \ Models \ Games', 'App \ Models \ Teams', 'id', 'home_id');
.. Avec cela, j'obtiens tous les matchs à domicile du club. Mais comment puis-je ajouter un ou
pour obtenir tous les matchs où les équipes du club sont à domicile ou des équipes invitées
Vous pouvez utiliser where
sur cette relation pour filtrer
plus loin
...-> games ()
ne renvoie que les jeux où home_id est un team_id du club. Lorsque je supprime les deux derniers paramètres (comme votre exemple), j'obtiens une exception SQL. Je ne peux pas ajouter de tableau au paramètre secondKey
de la fonction hasManyThrough
(par exemple, ['home_id', 'guest_id']
.
Merci de votre aide! Mais est-il possible de les fusionner et de les ordonner après la fusion?
Vous a donné un exemple de la façon dont vous pouvez fusionner ces 2 relations, remarquez comment j'ai appelé les relations sans crochets
, cela signifie que j'accède à la valeur et non à la requête
sous-jacente
Mais je ne peux pas utiliser -> orderBy (..) après la fusion. J'ai trouvé -> union (), mais cela fait toujours apparaître l'erreur "Nombre de colonnes différent", ce qui n'est pas possible
En effet, l'objet renvoyé par la fusion
n'est pas Eloquent Builder
qui a la méthode orderBy
, mais c'est un Collection code > qui a
sortBy
:) Pour voir toutes les méthodes disponibles que vous pouvez utiliser sur $ merged
, jetez un œil à ici
De plus, après la fusion, je vous recommande d'ajouter la méthode unique ()
à la collection de retour car il y aura beaucoup de duplication (un même match est joué entre l'équipe à domicile et l'équipe à l'extérieur, donc il existera dans les deux collections).
Merci d'avoir signalé une chose importante que j'ai totalement oublié @HCK
Je ne peux pas utiliser sortBy ('date') - car le tableau fusionné a ajouté des touches numériques. Après les avoir supprimés avec -> all (), je ne peux pas utiliser -> sortBy () car c'est un tableau ... c'est tellement frustrant ...
SortBy propose également un appelable au lieu d'un nom d'attribut
pour effectuer le tri. Je vais mettre à jour ma réponse avec un exemple maintenant
Heureux que vous l'ayez résolu et j'espère que vous avez appris un peu :) Vous êtes les bienvenus