Laravel多对多关联:获取仅含单个指定区域店铺信息的商品
解决方案:Laravel 5.3 多对多关联下仅获取指定城市单个店铺信息
问题回顾
你的多对多关联结构:
shops表:存储店铺信息,包含name、location_id、city_id字段items表:存储商品基础数据item_shop中间表:关联商品与店铺,包含item_id、shop_id字段
当前查询的核心问题是:with('shops')会拉取所有符合指定城市的店铺,数据冗余导致性能变慢,但你实际只需要单个店铺的信息。
方法一:定义专属“单店铺”关联(适合复用场景)
在Item模型中新增一个专门用于获取指定城市单个店铺的关联,替代原有的多对多shops关联:
// Item.php 模型文件 public function singleShopInCity($cityId) { return $this->belongsToMany(Shop::class, 'item_shop') ->where('shops.city_id', $cityId) ->select('shops.id', 'shops.name', 'shops.location_id') // 只拉取需要的字段,减少数据传输量 ->limit(1); // 强制仅返回一条店铺记录 }
查询时直接使用该关联预加载:
$items = Item::whereIn('items.id', $itemids) // 过滤出在指定城市有店铺的商品 ->whereHas('shops', function($q) use($city_id){ $q->where('shops.city_id', $city_id); }) // 预加载指定城市的单个店铺 ->with(['singleShopInCity' => function($q) use($city_id){ $q->where('shops.city_id', $city_id); }]) ->get();
后续直接通过$item->singleShopInCity->name获取店铺名称,无需再调用first()方法。
方法二:直接使用Join查询(性能最优,适合单次查询)
如果只是单次查询需求,直接通过表关联查询,一次SQL即可获取所有所需数据,避免预加载带来的额外查询和冗余数据:
$items = Item::whereIn('items.id', $itemids) ->join('item_shop', 'items.id', '=', 'item_shop.item_id') ->join('shops', 'item_shop.shop_id', '=', 'shops.id') ->where('shops.city_id', $city_id) ->select([ 'items.*', // 保留商品所有字段 'shops.id as shop_id', 'shops.name as shop_name', 'shops.location_id as shop_location_id' // 按需选择店铺字段 ]) ->groupBy('items.id') // 确保每个商品仅返回一条店铺记录 ->get();
查询完成后,直接通过$item->shop_name即可获取店铺名称,无需再处理关联集合。
内容的提问来源于stack exchange,提问作者Tom Kur
相关产品推荐
相关产品推荐

