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
相关产品推荐
相关产品推荐

