2017-11-07 4 views
0

Ich kämpfe um eifrig laden in Laravel arbeiten bei der Arbeit mit einem Drei-Wege-Pivot-Tisch. Die Datenbank wird wie folgt festgelegt:Eager laden Dreiweg Pivot-Tisch Laravel

+-------+--------+-------+-------------+ 
| deals | venues | users | redeems | 
+-------+--------+-------+-------------+ 
| id | id  | id | deal_id  | 
| title | name | name | user_id  | 
|  |  |  | venue_id | 
|  |  |  | redeemed_at | 
+-------+--------+-------+-------------+ 

Wo redeems ist offensichtlich die Pivot-Tabelle. Das Benutzermodell sieht wie folgt aus:

<?php 

class User extends Authenticatable 
{ 
    /** 
    * The deals redeemed by the user. 
    */ 
    public function deals() 
    { 
     return $this->belongsToMany(Deal::class, 'redeems') 
      ->withPivot(['venue_id', 'redeemed_at']); 
    } 
} 

Dies ermöglicht es mir, dies zu tun:

$users = Users::with('deals')->all(); 

Und dann bekomme ich einen schönen Überblick über den Benutzer und alle Angebote, die sie in eine Struktur eingelöst haben, wie dies:

{ 
    "id": 1, 
    "name": "Diederik", 
    "deals": [ 
    { 
     "id": 33, 
     "title": "Deal Title", 
     "pivot": { 
     "user_id": 1, 
     "deal_id": 33, 
     "venue_id": 50 
     } 
    } 
    ] 
} 

Nun möchte Ich mag den Ort Informationen von eifrigen Laden hinzuzufügen, es statt der $user->pivot->venue_id danach abfragt.

Ich habe versucht, eine belongsTo Beziehung im deal Modell einrichten und dann mit einer verschachtelten tun wie so: $users = Users::with('deals.venue')->all(); aber das funktioniert nicht, weil der Deal Tabelle keinen Fremdschlüssel zu einem Ort haben. Dies liegt daran, dass ein Deal für mehrere Veranstaltungsorte angewendet werden kann.

Ich bin mir bewusst, dass dies sehr einfach mit normalen Datenbankabfragen erreichbar ist, aber für die Art, wie unsere API funktioniert, ist es wichtig, die beredte with Relation Funktion zu verwenden, da unsere URL-Setup sucht nach Includes auf diese Weise.

TLDR: Wie man eifrig verschachtelte Drei-Wege-Pivot-Tabellenrelationen lädt.

Antwort

0

Wenn ich Ihre Frage richtig verstanden habe, haben Sie eine Eins-zu-viele-Beziehung zwischen Deals und Orten, an denen Sie einen bestimmten Veranstaltungsort erhalten möchten. Normalerweise würde man eine hasMany() oder belongsToMany() Beziehung in Ihren Angeboten Modell erstellen, dann, wenn Sie weiter die Spielstätten filtern mögen, würden Sie eine Eloquent Unterabfrage wie so schreiben:

// Gets first venue of deals 
Users::with('deals', 'deals.venues' => function ($query) { 
    $query->first(); 
})->all(); 
+0

Vielen Dank für Ihre Antwort. Die Beziehung zwischen "Deals" und "Venues" ist "Viele-zu-Viele". Ein Deal kann an mehreren Orten eingelöst werden und Veranstaltungsorte können mehrere verschiedene Angebote anbieten. Daher wird das, was Sie vorschlagen, nicht funktionieren, weil es eine andere Pivot-Tabelle ('deals_venue') gibt, die diese beiden verbindet. – Diederik

+0

Lassen Sie mich umformulieren: Was Sie vorschlagen, funktioniert, aber dann werde ich alle Veranstaltungsorte erhalten, die diesen Deal anbieten, nicht den bestimmten Ort, an dem der Deal eingelöst wird. Die Beziehung zwischen den Spielstätten und den Abschlüssen spielt für meine Frage keine Rolle, weshalb ich sie von meiner ursprünglichen Frage ausgelassen habe. – Diederik

0

Ich würde sugest Sie behandeln die Pivot-Tabelle als ein anderes Modell (Einlösen). Dann Eins-zu-viele machen Beziehungen mit den anderen Tabellen/models (Deal/Ort/User), so dass Sie konnte einfach Ihre Anfrage machen die Objekte mit Eloquent wie diese zu faul Last, die Sie brauchen:

$redeems = User::find($id)->redeems; 
$redeems->load(['venue','deal']); 

return $redeems; 

das Formatieren Daten/Antwort in einer genauen Weise können Sie API Resources verwenden, wenn Sie 5.5 verwenden. Oder Fractal für 5.4 oder darunter.

+0

Natürlich danke ich Ihnen für Ihre Antwort, aber ich muss gestehen, dass ich das Problem tatsächlich behoben habe, wie Sie es vorgeschlagen haben. Aus Gründen der Argumentation habe ich die Frage hier trotzdem gestellt. In gewisser Weise fühlt es sich ein bisschen so an, als würde man auf diese Weise betrügen. Außerdem können Sie jetzt keine ausgefallenen Funktionen wie 'attach' und/oder' sync' verwenden, oder? Ich habe mich nur gefragt, ob es einen anderen Weg gab. – Diederik