2016-12-17 2 views
0

Ich fand ein sehr bizarres Verhalten von with Funktion für die Überladung Beziehungen. Ich habe Product und Deal Beziehungen, so dass ProductbelongsTo()Deal (über product_id in deals Tabelle). Jetzt, wenn ich versuche, alle zum Verkauf angebotenen Produkte zu erhalten:Einschränkung eifrig geladene Beziehung

Product::with(['deal' => function($query) { 
    $query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString()); 
}])->get() 

dies gibt eine Sammlung von alle Produkte, obwohl es keine Datensätze in deals Tabelle und alle Produkte haben deal_id Set NULL . Zur gleichen Zeit gibt Product::has('deal')->get() eine leere Sammlung zurück, wie Sie es erwarten würden.

entdecken ich zunächst dieses Problem bei dem Versuch, fünf zufällige Produkte auf dem Verkauf mit Deal und Image Beziehungen zusammen zu holen:

Product::with(['deal' => function ($query) { 
     $query->whereDate('ends_at', '>', // promo still active 
          Carbon::now()->toDateTimeString()); 
    }, 
    'images' => function ($query) { 
     $query->where('featured', true); // image featured on homepage 
    }]) 
->where('status', 'IN_STOCK') // 'In Stock' 
->whereNull('deleted_at')  // wasn't soft-deleted 
->orderByRaw('RAND()') 
->take(5)->get()) 

Diese aus allen Product s eine Sammlung mit 5 zufälligen Product s ergeben. Ich habe versucht mit query->whereNotNull('ends_at')->whereDate('ends_at' .....);, aber die gleichen Ergebnisse.

Was mache ich hier falsch?

Antwort

1

Ihr Verständnis des Konzepts ist hier völlig falsch.

Wenn Sie sagen, dass ein ProduktbelongsTo()Deal, dann vermuten lässt, dass ein DealhasMany()Produkte.

Dies ist die Tabelle Angebote

deals 
id | name | ends_at | blah | blah 

products 
id | deal_id | name | blah | blah 

Also im Grunde sollte die Product::with('deal') zurückkehren Sie alle Produkte mit ihren Angebote Eager geladen. Aber Deal::with('products') wird Ihnen eine leere Sammlung zurückgeben, da keine Produkte eine gültige deal_id drin haben.

Es ist wichtig zu beachten, dass, da Produkt können belongTo nur ein einziger Deal, werden Sie immer den Deal Modell erhalten, anstatt eine Sammlung, wenn Sie Product::with('deal') Abfrage durchführen. Aber wenn Sie Deal::with('products') durchführen, sind Sie verpflichtet, eine Sammlung zu erhalten.

Also im Grunde, wenn Sie sagen,

Diese eine Sammlung aller Produkte zurückgibt, obwohl es keine Einträge in der Tabelle Angebote und alle Produkte haben deal_id auf NULL gesetzt.

Es ist ziemlich offensichtlich, .... weil die Abfrage hier erfolgt auf Produkte und nicht Deal. Wenn Sie versuchen, die Deal wo ends_at > Carbon::now() zu finden, müssen Sie dies tun.

Deal::with('product')->where('ends_at', '>', Carbon::now()->toDateTimeString()) 
+0

Oh, ich sehe, ich es rückwärts bekam. Danke für das Aufzeigen! – Alex

0

Wenn Sie with verwenden dann nur eifrig lädt die Beziehungen zu den Einschränkungen zur Verfügung gestellt, aber wenn Sie das übergeordnete Modell durch ihre Beziehungen filtern wollen, dann ist whereHas dein Freund. So sollte Ihre Frage sein, wie:

Product::whereHas('deal' => function($query) { 
      $query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString()); 
     })->get(); 

Jetzt holen sie nur diejenigen Product, die die gegebene Bedingung erfüllen.

Sie können auch die Kombination von with verwenden und whereHas als:

Product::whereHas('deal' => function($query) { 
      $query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString()); 
     }) 
     ->with(['deal' => function($query) { 
      $query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString()); 
     }]) 
     ->get(); 
Verwandte Themen