2017-09-21 1 views
1

Ich habe zwei Modelle über eine Pivot-Tabelle mit einer zusätzlichen Spalte verbunden, um die Menge für meine BefehleEager Laden einzelner many-to-many-Beziehung

class Item extends Eloquent { 
    public function containers() 
    { 
     return $this->belongsToMany('Container', 'items_containers', 'item_id', 'container_id')->withPivot(['quantity']); 
    } 
} 

class Container extends Eloquent { 
    public function items() { 
     return $this->belongsToMany('Item', 'items_containers', 'container_id', 'item_id')->withPivot(['quantity']); 
    } 
} 

Und ein drittes Modell zu verfolgen:

class OrderItem extends Eloquent { 
    public function originalItem() 
    { 
     return $this->hasOne('Item', 'id', 'item_id'); 
    } 
    public function container() { 
     return $this->hasOne('Container', 'id', 'container_id'); 
    } 

} 

Ich möchte die spezifischen Daten aus der Pivot-Tabelle abrufen können, wenn ich eifrig die OrderItem-Modelle lade. Daher erhalte ich nur die Menge, in der item_id und container_id mit denen auf dem Bestellartikel übereinstimmen.

OrderItems::whereOrderId($orderId) 
    ->with(['originalItem', 'container', '???']) 
    ->get(); 

Was ist der beste Weg, um die Beziehung auf der OrderItem angeben, oder sie laden mit with?

+0

Ich verstehe nicht wirklich Ihre Struktur, tut mir leid, wenn ich falsch verstanden habe. Der eloquente Weg, sich Modellen anzuschließen, ist so etwas. $ orderItem = OrderItems :: find ($ orderId); $ orderItem-> originalItem; $ orderItem-> container; – Christ

+0

10 Der Hauptzweck der Verwendung des Befehls "with" besteht darin, dass ich die Daten an eine angularjs-App zurücksende. Ich kann den ursprünglichen Artikel und Container den ganzen Tag lang erhalten, aber ich muss den spezifischen Mengenwert erhalten, der in der Pivot-Tabelle items_containers lebt. – aynber

Antwort

2

Der folgende Code gibt, was Sie wollen:

$orders = \App\OrderItem::select('item_orders.*', 'items_containers.quantity as quantity')->with('item', 'container') 
    ->leftJoin('items_containers', function ($join) { 
     $join->on('items_containers.item_id', 'item_orders.item_id') 
      ->where('items_containers.container_id', \DB::raw('item_orders.container_id')); 
    }) 
    ->get(); 

Dann können Sie bequem die Menge bekommen.

$orders->first()->quantity; 

Das ist es.

+0

Natürlich, Attribute! Ich vergesse das immer wieder. Ich werde das ausprobieren und Sie wissen lassen. – aynber

+0

Es hat mich nicht ganz erreicht, aber es hat mich definitiv auf die richtige Spur gebracht. Ein Teil des Schlüssels war in der Lage zu sein, es automatisch zu laden, so dass ich es in einer json Antwort zurückgeben konnte, folglich die 'mit' Schlüsselwörter. – aynber

+0

Ich sehe. Sie müssen über eine Menge verfügen, um Teil der OrderItem-Auflistung zu sein. –

1

Hauptstützen für Morteza Rajabi, um mich auf die richtige Spur zu bringen. Der erste Schlüssel war das Abrufen der spezifischen Beziehung, da Elemente und Container eine Viele-zu-Viele-Beziehung sind und das Bestellelement eine Eins-zu-Eins-Beziehung sowohl mit dem Objekt als auch dem Container hat. Um die spezifische Beziehung Menge zu bekommen, musste ich es ein Attribut erstellen Angabe:

public function getItemContainerQtyAttribute() { 
    if($this->item_id && $this->container_id) { 
     return $this->depoItem->containers()->where('items_containers.container_id', $this->container_id)->first()->pivot->quantity; 
    } 
    return null; 
} 

Die item_id und container_id Kontrolle ist, weil dies ein work in progress und die Orderitem nicht immer korrekt erstellt wurden, und bei einigen Artikeln ist kein Container angegeben.

Der nächste Schritt war automatisch zu laden es mit dem appends Attribut innerhalb Eloquent:

protected $appends = ['item_container_qty']; 

Nun, wenn ich $item = OrderItems::whereOrderId($order_id)->get(); laden, wird es die die Drehmenge automatisch geladen.

+0

Es macht den Job, aber es ist nicht effizient. Es wird N + 3 Abfragen für N Bestellungen machen. –

+0

Ihr Recht, und JsonSerialize bellt daran. Ich werde das noch ein wenig verbessern müssen. – aynber

+0

Warum verwenden Sie keine Joins? –