1
votes

Laravel - Relation éloquente oùA une ou plusieurs autres relations

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');
    }


0 commentaires

3 Réponses :


0
votes

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.


2 commentaires

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".



0
votes

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');
    }


0 commentaires

2
votes

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;
});

EDIT # 01

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();

EDIT # 02

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');
}


12 commentaires

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 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