Laravel Eloquent 通过其他关系求和关系的列
Laravel Eloquent sum relation's column through other relation
假设我有这些模块:
- 优惠券
- 订单 (.., coupon_id)
- 商品(...,order_id,价格)
还有那些关系:
Coupon
有很多 Order
.
Order
有很多 Item
.
到目前为止一切顺利。
现在我想对属于优惠券的订单的商品的价格求和。所以我想做这样的事情:
Coupon::orders->items->sum('price');
嗯,它不会工作,因为 orders()
方法 returns 一个 Collection
的关系:
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function orders()
{
return $this->hasMany(Order::class);
}
我收到一条错误消息,提示 item
属性 受保护。我发现它与我的 Item
模块无关,只是因为 Collection
有 protected $items = [];
.
所以,在我清除了一些事实之后,我的question/problem是,我如何求和属于Coupon
的orders
的items->price
?
当然,我可以通过这样的 foreach 循环来实现我的目标:
$price = 0;
foreach (Coupon:orders as $order)
$price += $order->items->sum('price');
return $price;
但我正在寻找更简洁的解决方案。有人吗?
实现该目标的几种方法:
$coupon_id; // the one you're looking for
Item::whereHas('order', function ($q) use ($coupon_id) {
$q->where('coupon_id', $coupon_id);
})->sum('items.price');
// OR
// Coupon model
public function items()
{
return $this->hasManyThrough(Item::class, Order::class);
}
Coupon::find($coupon_id)->items()->sum('price') // aggregate query
Coupon::find($coupon_id)->items->sum('price') // sum on collection
// OR
Coupon::with('orders.items')->find($coupon_id)->orders->pluck('items')->collapse()->sum('price');
假设我有这些模块:
- 优惠券
- 订单 (.., coupon_id)
- 商品(...,order_id,价格)
还有那些关系:
Coupon
有很多Order
.Order
有很多Item
.
到目前为止一切顺利。
现在我想对属于优惠券的订单的商品的价格求和。所以我想做这样的事情:
Coupon::orders->items->sum('price');
嗯,它不会工作,因为 orders()
方法 returns 一个 Collection
的关系:
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function orders()
{
return $this->hasMany(Order::class);
}
我收到一条错误消息,提示 item
属性 受保护。我发现它与我的 Item
模块无关,只是因为 Collection
有 protected $items = [];
.
所以,在我清除了一些事实之后,我的question/problem是,我如何求和属于Coupon
的orders
的items->price
?
当然,我可以通过这样的 foreach 循环来实现我的目标:
$price = 0;
foreach (Coupon:orders as $order)
$price += $order->items->sum('price');
return $price;
但我正在寻找更简洁的解决方案。有人吗?
实现该目标的几种方法:
$coupon_id; // the one you're looking for
Item::whereHas('order', function ($q) use ($coupon_id) {
$q->where('coupon_id', $coupon_id);
})->sum('items.price');
// OR
// Coupon model
public function items()
{
return $this->hasManyThrough(Item::class, Order::class);
}
Coupon::find($coupon_id)->items()->sum('price') // aggregate query
Coupon::find($coupon_id)->items->sum('price') // sum on collection
// OR
Coupon::with('orders.items')->find($coupon_id)->orders->pluck('items')->collapse()->sum('price');