Laravel:在嵌套关系中求和一个属性

问题描述:

我想对一个嵌套集合求和。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; 
} 

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

有没有更好的方法来做到这一点?

洁版,但效率不高

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

是的,但如果你知道如何做这个清洁剂,我会很高兴,我试着得到相同的东西,但平均(),这种解决方案可能不是有效的,但即使最脏我不能这样做:( –