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

Laravel中whereRelation/whereHas无法过滤关联数据问题求助

问题:无法正确筛选关联商户状态的Offer

需求描述

筛选出满足以下所有条件的Offer:

  • 关联商户(通过mid字段关联)状态为Open且dd_merchant为1
  • Offer自身状态为Loaded
  • Offer日期在有效期内(start ≤ 当前日期,end ≥ 当前日期)
  • 符合指定分类$request->category

Offer模型关联定义

public function merchants()
{
    return $this->belongsTo(Merchant::class,'mid','mid');
}

尝试过的查询写法

  1. 多次调用whereRelation:
$data['offers']= Offer::whereRelation('merchants', 'status', 'Open')
      ->whereRelation('merchants', 'dd_merchant', '1')
      ->where('status', '=', 'Loaded')
      ->where("start", "<=", date("Y-m-d"))
      ->where("end", ">=", date("Y-m-d"))
      ->where('category', '=', $request->category)
      ->orderBy('title','ASC')
      ->paginate(20);
  1. 使用whereHas闭包:
$data['offers']= Offer::
    whereHas('merchants', function (Builder $query) {
        $query->where('dd_merchant', '=', '1')->where('status', '=', 'Open');
    })
    ->where('status', '=', 'Loaded')
    ->where("start", "<=", date("Y-m-d"))
    ->where("end", ">=", date("Y-m-d"))
    ->where('category', '=', $request->category)
    ->orderBy('title','ASC')
    ->paginate(20);

问题现象

数据库中存在状态为Closed、dd_merchant为0的商户,但上述两种查询仍返回该商户的Offer,筛选逻辑未生效。


解决方案

1. 先排查基础数据与关联问题

  • 字段类型匹配:确认Offer表和Merchant表的mid字段数据类型完全一致(比如同为字符串或整数),类型不匹配会导致关联失效,筛选条件无法作用。
  • 字段值大小写/类型:检查Merchant表中status的存储值是否为Open(注意大小写);dd_merchant如果是数值类型,查询时要用1而非'1',字符串类型则保持引号。

2. 修正后的查询写法

如果数据层面没问题,推荐用whereHas合并关联条件,同时用whereDate优化日期查询(避免字符串格式冲突):

use Illuminate\Database\Eloquent\Builder;

$data['offers'] = Offer::whereHas('merchants', function (Builder $query) {
        // 根据实际字段类型调整dd_merchant的值(数值就去引号)
        $query->where('status', 'Open')
              ->where('dd_merchant', 1);
    })
    ->where('status', 'Loaded')
    // 使用whereDate处理日期,更可靠
    ->whereDate('start', '<=', now()->toDateString())
    ->whereDate('end', '>=', now()->toDateString())
    ->where('category', $request->category)
    ->orderBy('title', 'ASC')
    ->paginate(20);

3. 排查模型全局干扰项

  • 检查Merchant模型是否开启软删除,如果是,需要确保whereHas中只包含未删除的商户(默认会自动过滤,若有特殊需求可加->withTrashed())。
  • 确认两个模型没有全局作用域(比如默认添加的筛选条件),避免干扰关联查询逻辑。

4. 打印SQL排查细节

可以生成SQL语句直接在数据库执行,验证条件是否正确应用:

$sql = Offer::whereHas('merchants', function (Builder $query) {
        $query->where('status', 'Open')->where('dd_merchant', 1);
    })
    ->where('status', 'Loaded')
    ->whereDate('start', '<=', now()->toDateString())
    ->whereDate('end', '>=', now()->toDateString())
    ->where('category', $request->category)
    ->orderBy('title', 'ASC')
    ->toSql();

dd($sql); // 打印生成的SQL语句

内容的提问来源于stack exchange,提问作者Patrick Simard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 01:31:00