Laravel 雄辩用 whereHas 或其他限制 withCount
Posted
技术标签:
【中文标题】Laravel 雄辩用 whereHas 或其他限制 withCount【英文标题】:Laravel eloquent restrict withCount with whereHas or another 【发布时间】:2021-12-24 22:58:38 【问题描述】:我有 3 个模型 Supplier
、Purchase
和 PurchaseDetail
。
为了通过 Purchase 将 Supplier 模型与 PurchaseDetail 加入,我创建了一个 hasManyThrough 关系。
hasManyThrough
内Supplier
模型:
public function detail_purchases()
return $this->hasManyThrough(PurchaseDetail::class, Purchase::class);
关系很好,我可以计算从卖家那里购买的数量如下:
$collectors = Supplier::withCount(['detail_purchases as qty_sold' => function($query)
return $query->select(\DB::raw('SUM(qty)'))
->where('unit', '=', 'kg');
])
->where('supplier_type','=','persona_natural')
->orderBy('qty_sold','desc')
->get();
SQL 查询输出:
select `suppliers`.*, (
select SUM(qty)
from `purchase_details`
inner join `purchases` on `purchases`.`id` = `purchase_details`.`purchase_id`
where `suppliers`.`id` = `purchases`.`supplier_id`
and `unit` = 'kg'
and `purchases`.`deleted_at` is null
) as `qty_sold`
from `suppliers`
where `supplier_type` = 'persona_natural'
order by `qty_sold` desc;
输出行:
我的问题是,这个查询给我带来了我没有从他们那里购买过的卖家,我不知道如果假设 hasManyThrough 关系只加入那些在 Purchase 中注册或制作的人,他们为什么会渗透到查询中从他们那里购买。
Supplier
模型还有另一个称为purchases
的关系:
public function purchases()
return $this->hasMany(Purchase::class, 'supplier_id');
并且模型Purchase
与 PurchaseDetail 有关系 hasMany :
public function details()
return $this->hasMany(PurchaseDetail::class, 'purchase_id');
更新
使用 whereHas now 我可以获取我购买的所有供应商,但是 qty_sold 没有出现在结果中:
$collectors = Supplier::whereHas('purchases', function($query)
$query->withCount(['details as qty_sold' => function($query)
$query->select(\DB::raw('SUM(qty)'))
->where('unit', '=', $this->unit);
]);
)
->where('supplier_type','=','persona_natural')
->get();
此选择很重要,因为我想知道我购买的所有产品中有多少 kgs
。
【问题讨论】:
通过将->get()
替换为->toSql()
来获取执行的SQL 查询,并将结果发布到您的问题中。这可能有助于理解为什么要包括其他供应商。
嗨@Tony 我已经更新了我的问题,检查它..这是扔掉所有供应商..
@Tony 我已经更新了,看看就完事了。 whereHas 有效,但 SUM 未出现在结果中。
在您更新的查询中,您可以将withCount
移出子查询吗?所以你会得到Supplier::withCount(...)->whereHas('purchases')...
在尝试构建更复杂的查询时,我做的另一件事是用 SQL 将其写出来,然后开始将其转换为 PDO 查询,然后再转换为 Eloquent。它还有助于逐位构建查询:从检索正确的行开始,然后进行聚合。
查看您的第一个查询,它选择了所有供应商,然后执行子查询以获取计数,因为使用您的 hasManyThrough
表连接的表仅在子查询中。
【参考方案1】:
谢谢@托尼
在您更新的查询中,您可以将 withCount 移出子查询吗?所以你会有 Supplier::withCount(...)->whereHas('purchases')..
好的,我修复了它,首先添加 whereHas
指令,然后我使用了 hasManyThrough
与withCount
的关系。通过这种方式,只有购买过的供应商才是选择。
$collectors = Supplier::whereHas('purchases')
->withCount([
'detail_purchases as qty_sold' => function($query)
$query->select(\DB::raw('SUM(qty)'))
->where('unit', '=', 'kg');
])
->where('supplier_type','=', 'persona_natural')
->get();
【讨论】:
很高兴听到你成功了以上是关于Laravel 雄辩用 whereHas 或其他限制 withCount的主要内容,如果未能解决你的问题,请参考以下文章
SQLSTATE[HY000] [2002] 使用 whereHas 时 laravel 中的连接被拒绝错误
雄辩的多个 whereHas('pivot_table_X') AND whereHas('pivot_table_X')