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

Laravel 9中用whereHas对比关联字段筛选AcceptedOrder的方法

Laravel 9 多模型关联条件查询实现

需求分析

需要筛选出满足以下条件的AcceptedOrder记录:

  • 关联的Order与Shop的city_id相同时,Order的updated_at需早于4小时前
  • 关联的Order与Shop的city_id不同时,Order的updated_at需早于2天前
  • 最终结果按created_at降序排列

实现方案

利用whereHas关联查询,结合表关联与字段对比来实现条件判断。由于需要对比Order和Shop的city_id,需在whereHas的闭包中通过join关联对应的数据表,确保能获取到两个模型的字段值进行对比。

代码实现(条件分支写法)

use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

$acceptedOrders = AcceptedOrder::from('accepted_orders as main_ao')
    ->whereHas('order', function ($orderQuery) {
        // 关联当前AcceptedOrder对应的Shop记录
        $orderQuery->join('accepted_orders as join_ao', 'orders.id', '=', 'join_ao.order_id')
                   ->join('shops', 'join_ao.shop_id', '=', 'shops.id')
                   // 限定关联的是当前主查询的AcceptedOrder记录,避免匹配无关数据
                   ->where('join_ao.id', '=', DB::raw('main_ao.id'))
                   ->where(function ($q) {
                       // 分支1:同城市,订单更新时间早于4小时前
                       $q->where(function ($subQ) {
                           $subQ->whereColumn('orders.city_id', 'shops.city_id')
                                ->where('orders.updated_at', '<', Carbon::now()->subHours(4));
                       })
                       // 分支2:不同城市,订单更新时间早于2天前
                       ->orWhere(function ($subQ) {
                           $subQ->whereColumn('orders.city_id', '!=', 'shops.city_id')
                                ->where('orders.updated_at', '<', Carbon::now()->subDays(2));
                       });
                   });
    })
    ->orderBy('main_ao.created_at', 'desc')
    ->get();

代码实现(whereRaw简洁写法)

如果觉得条件分支写法繁琐,也可以用whereRaw直接编写复合条件,代码更简洁:

use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

$acceptedOrders = AcceptedOrder::from('accepted_orders as main_ao')
    ->whereHas('order', function ($orderQuery) {
        $orderQuery->join('accepted_orders as join_ao', 'orders.id', '=', 'join_ao.order_id')
                   ->join('shops', 'join_ao.shop_id', '=', 'shops.id')
                   ->where('join_ao.id', '=', DB::raw('main_ao.id'))
                   ->whereRaw("
                       (orders.city_id = shops.city_id AND orders.updated_at < ?)
                       OR
                       (orders.city_id != shops.city_id AND orders.updated_at < ?)
                   ", [Carbon::now()->subHours(4), Carbon::now()->subDays(2)]);
    })
    ->orderBy('main_ao.created_at', 'desc')
    ->get();

代码说明

  1. 使用from('accepted_orders as main_ao')给主查询的表设置别名,避免与join的表名冲突;
  2. 在whereHas('order')的闭包中,通过join关联accepted_orders(别名join_ao)和shops表,获取当前Order对应的Shop数据;
  3. 通过where('join_ao.id', '=', DB::raw('main_ao.id'))确保关联的是当前主查询的AcceptedOrder记录,不会匹配到其他无关的关联数据;
  4. 用whereColumn或whereRaw对比Order和Shop的city_id,并结合时间条件筛选数据;
  5. 最后通过orderBy按created_at降序排列结果。

内容的提问来源于stack exchange,提问作者aref razavi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:26:05