2017-06-02 39 views
2

我想對一個嵌套集合求和。Laravel:在嵌套關係中求和一個屬性

我有以下表格:

  • 場地
  • 信息
  • 訂單

一個venue可以有很多offersoffer可以有很多orders

實施例的數據可以是:

場地

id  | name 
========================== 
5   | Pizza 4 Less 
10  | Poundland 

信息

id | venue_id | name 
================================== 
17 | 5  | Buy 1 get one free 
24 | 5  | 30% off pizza 
32 | 10  | 50% off 
50 | 10  | 20% off 

訂單

id | offer_id | bill | paid 
=========================== 
85 | 17  | 15 | true 
86 | 17  | 20 | true 
87 | 17  | 90 | true 
88 | 24  | 14 | true 
89 | 32  | 15 | true 
90 | 32  | 65 | true 
91 | 50  | 24 | true 
92 | 50  | 1000 | false 

我想使用Laravel Elqouent模型來獲得每個場地支付的總金額。因此,對於上述數據我希望得到以下結果:

id | name   | total_paid 
=============================== 
5 | Pizza 4 Less | 139 
10 | Poundland  | 104 

注意,總計不包括尚未支付(即爲了92)

的方式令我目前做的,這是如下:

$venues = Venue::with(['offers.orders' => function ($query) { 
     $query->where('paid', '=', true); 
    }]) 
    ->get(); 

$totals = []; 
foreach ($venues as $venue) { 
    $totalPaid = 0; 
    foreach ($venue->offers as $offer) { 
     $totalPaid += $offer->orders->sum('bill'); 
    } 
    $totals[$venue->name] = $totalPaid; 
} 

正如你所看到的,上面的代碼是低效率和長。

有沒有更好的方法來做到這一點?

回答

2

潔版,但效率不高

// In your Venue Model 
public function getTotalPaidAttribute() 
{ 
    return $this->offers->sum('TotalPaid'); 
} 

// In your Offer Model 
protected $appends = ['totalPaid']; 

public function getTotalPaidAttribute() 
{ 
    return $this->orders->sum('paid'); 
} 

// use it : 
foreach($venues as $venue){ 
    //do what you want with it 
    $venue->totalPaid; 
} 

(編輯)

正如評論說,這種方法可能是更清潔,但效率不高:

有效途徑:

// In your Venue Model 
public function orders(){ 
    return $this->hasManyThrough(Order::class, Offer::class) 
     ->selectRaw('sum(paid) as aggregate, venue_id') 
     ->groupBy('venue_id'); 
} 

public function totalPaid(){ 
    if (! array_key_exists('orders', $this->relations)) $this->load('orders'); 
    $relation = $this->getRelation('orders'); 

    return ($relation) ? $relation->aggregate : 0; 
} 

public function getTotalPaidAttribute() 
{ 
    return $this->totalPaid(); 
} 

也許我搞砸了你的鑰匙,你可能不得不使用完整的declar關係的通貨膨脹:

return $this->hasManyThrough(
     Order::class, Offer::class 
     'venue_id', 'offer_id', 'id' 
    ); 

,但我只是用我的項目沒有和它的工作原理就像一個魅力

+0

清潔和有組織 –

+1

這可能是乾淨的,但效率不高。試着用幾千行來運行基準測試,你就會明白。 – Sandeesh

+0

是的,但如果你知道如何做這個清潔劑,我會很高興,我試着得到相同的東西,但平均(),這種解決方案可能不是有效的,但即使最髒我不能這樣做:( –