Laravel如何按嵌套关联模型的字段对查询结果进行排序
问题根因
你当前写法存在两个核心问题:
whereHas仅用于过滤「存在对应关联的订单记录」,闭包内的排序逻辑只作用在关联存在性检查的子查询中,完全不会影响主查询的结果排序,所以排序不生效。- 你没有使用关联预加载逻辑,因此返回的订单结果中不会附带关联的user和company数据。
解决方案
方案1:JOIN联表排序(推荐,性能高、支持分页)
直接通过联表将company的title字段加入主查询排序,同时配合预加载获取关联数据:
$direction = $request->get('orderByDirection') ?? 'asc'; $orders = OrderModel::query() // 预加载关联,返回结果可直接访问owner、company属性 ->with('owner.company') // 关联用户表 ->join('users', 'orders.owner_id', '=', 'users.id') // 关联公司表 ->join('companies', 'users.company_id', '=', 'companies.id') // 按公司title排序 ->orderBy('companies.title', $direction) // 仅选取订单表字段,避免关联表同名字段覆盖主模型属性 ->select('orders.*') ->get();
如果需要分页,将末尾的get()替换为paginate(分页条数)即可正常使用。
方案2:集合排序(仅适用于数据量小的全量查询场景)
查询出所有订单后,通过集合方法对结果排序:
$direction = $request->get('orderByDirection') ?? 'asc'; $orders = OrderModel::query() ->with('owner.company') ->get() ->sortBy('owner.company.title', ascending: $direction === 'asc');
该方案需要先查询出全量订单再排序,数据量较大时性能很低,也不支持分页。
注意事项
如果你的表名、外键字段和示例不一致,需要替换为你实际的数据库表名和字段定义。
内容的提问来源于stack exchange,提问作者Afzal Ali
相关产品推荐
相关产品推荐

