You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel多对多关系下按最新状态筛选订单异常问题

解决方案

1. 优化Order模型关联

在Order模型中新增关联,专门获取订单的最新状态记录:

// Order.php
public function latestStatus()
{
    return $this->hasOne(OrderStatus::class)->latest('created_at');
}

注:若未创建OrderStatus模型(对应order_status表),建议补充创建,便于后续查询操作。

2. 正确筛选最新状态的订单

要确保筛选的是每条订单的最新状态,而非旧状态,可通过以下两种方式实现:

方法一:子查询筛选

$targetStatusId = 2; // 目标状态ID

$orders = Order::query()
    ->with(['latestStatus.status']) // 预加载最新状态及关联的Status模型
    ->whereHas('latestStatus', function ($query) use ($targetStatusId) {
        $query->where('status_id', $targetStatusId);
    })
    ->paginate(13);

方法二:Join关联最新状态记录

若追求更高查询效率,可通过Join关联最新状态的子查询结果:

$targetStatusId = 2;

$orders = Order::query()
    ->select('orders.*')
    ->joinSub(
        OrderStatus::select('order_id', 'status_id')
            ->selectRaw('MAX(created_at) as latest_created')
            ->groupBy('order_id'),
        'latest_order_status',
        function ($join) {
            $join->on('orders.id', '=', 'latest_order_status.order_id');
        }
    )
    ->join('order_status', function ($join) {
        $join->on('orders.id', '=', 'order_status.order_id')
             ->on('order_status.created_at', '=', 'latest_order_status.latest_created');
    })
    ->where('order_status.status_id', $targetStatusId)
    ->with(['latestStatus.status'])
    ->paginate(13);

3. 修复分页异常问题

之前分页仅返回最后一批数据,核心原因是查询逻辑错误地对关联表记录分页,而非主订单表。上述两种方法均基于Order模型查询构建器调用paginate(),会正确对订单数据分页,每页返回13条符合条件的订单。

关键注意点

  • 必须确保筛选条件针对每条订单的最新状态记录,否则会出现筛选出含旧状态订单的问题;
  • 使用with(['latestStatus.status'])预加载关联数据,可避免N+1查询,提升性能。

内容的提问来源于stack exchange,提问作者Jafrul tripto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 03:23:09