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

Laravel Eloquent多表关联查询问题:按商场名称搜商品出错

问题分析与解决方案

你这段代码报错的核心原因很明确:with('shop', 'shop.mall')只是预加载关联模型,它会在主查询(查products表)之后再单独查shops和malls表,并不会把这两个表的数据合并到主查询的WHERE条件判断里。所以你直接在where()里写shop.mall.name这种嵌套关联字段,数据库根本找不到这个列——主查询里只有products表的字段呀!

下面给你两种可行的修复方案,按需选择:

方案一:使用whereHas嵌套关联查询(推荐,符合Laravel Eloquent的写法)

whereHas的作用就是检查关联模型是否存在满足条件的记录,刚好适配这种嵌套关联的过滤场景:

$query = Product::with('shop', 'shop.mall');
if (!empty($data["keyword"])) {
    $query = $query->whereHas('shop', function($shopQuery) use($data) {
        // 先关联到店铺,再检查店铺关联的商场是否匹配关键词
        $shopQuery->whereHas('mall', function($mallQuery) use($data) {
            $mallQuery->where('name', 'LIKE', '%' . $data["keyword"] . '%')
                      ->orWhere('keyword', 'LIKE', '%' . $data["keyword"] . '%');
        });
    });
}

这种写法完全遵循Eloquent的关联逻辑,而且不需要手动处理表关联的细节,还能保留预加载的性能优势。

方案二:手动join关联表(适合对查询性能有更高要求的场景)

如果你的数据量很大,担心whereHas生成的子查询性能不够,可以直接手动join三张表,然后直接对malls表的字段做过滤:

$query = Product::with('shop', 'shop.mall')
    ->join('shops', 'products.shop_id', '=', 'shops.id')
    ->join('malls', 'shops.mall_id', '=', 'malls.id');

if (!empty($data["keyword"])) {
    $query = $query->where(function($q) use($data) {
        $q->where('malls.name', 'LIKE', '%' . $data["keyword"] . '%')
          ->orWhere('malls.keyword', 'LIKE', '%' . $data["keyword"] . '%');
    });
}

// 注意:关联查询可能会出现重复的商品记录,记得加上distinct去重
$query = $query->distinct();

额外提醒

确保你的模型已经正确定义了关联关系:

  • Product模型:
public function shop()
{
    return $this->belongsTo(Shop::class);
}
  • Shop模型:
public function mall()
{
    return $this->belongsTo(Mall::class);
}

内容的提问来源于stack exchange,提问作者Redzwan Latif

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:09:34