Laravel 5.4:如何在Eloquent的whereHas中使用groupBy
在Laravel 5.4的whereHas闭包中使用groupBy的解决方案
其实很简单,你可以直接在whereHas的关联查询闭包里调用groupBy方法——因为闭包中的$query是针对关联表(这里是orderDetail对应的表)的查询构建器实例,所有查询构建器支持的方法(包括分组、聚合、过滤等)都能在这里正常使用。
修改后的完整代码示例
use Illuminate\Support\Facades\Auth; public function index(Request $request) { $dateFrom = $request->get('dateFrom'); $dateTo = $request->get('dateTo'); $status = $request->get('orderState'); $orders = (new OrderList()) ->whereHas('orderDetail', function ($query) { $query->where('supplier_id', Auth::guard('supplier')->user()->id) // 替换成你实际需要分组的字段,比如关联表中的order_id ->groupBy('order_id'); }) ->when($dateFrom, function ($query) use ($dateFrom, $dateTo) { // 补全你之前的时间范围过滤逻辑,比如针对订单创建时间 $query->whereBetween('created_at', [$dateFrom, $dateTo]); }) // 可选:根据订单状态添加过滤条件 ->when($status, function ($query) use ($status) { $query->where('order_state', $status); }) ->get(); return $orders; }
进阶用法:结合聚合函数与having过滤
如果你需要在分组后基于聚合结果进一步筛选(比如只保留关联记录数大于1的订单),可以配合select和havingRaw实现:
use Illuminate\Support\Facades\DB; // ...其他代码不变 ->whereHas('orderDetail', function ($query) { $query->where('supplier_id', Auth::guard('supplier')->user()->id) ->select('order_id', DB::raw('count(*) as item_count')) ->groupBy('order_id') // 只保留关联商品数量大于1的订单 ->havingRaw('item_count > 1'); }) // ...其他代码不变
注意事项
- 如果开启了MySQL严格模式,
groupBy需要包含所有select语句中的非聚合字段,否则会抛出SQL语法错误。 whereHas的核心作用是筛选出存在符合条件关联记录的主模型(OrderList),所以分组操作只会影响关联表的查询逻辑,不会直接改变主模型的结果结构(如果需要统计关联数据,可以配合withCount方法)。
内容的提问来源于stack exchange,提问作者Yousef Altaf
相关产品推荐
相关产品推荐

