Laravel使用Join关联查询时如何获取指定产品的全部属性记录
解决方案
方案1:使用Eloquent一对多关联(推荐)
这是Laravel框架下处理此类一对多数据查询的最优方式,无需手动写JOIN逻辑,数据结构天然符合需求:
- 先在
Product模型中定义和属性表的关联关系
// app/Models/Product.php public function attributes() { return $this->hasMany(ProductAttribute::class, 'product_id', 'id'); }
- 查询时直接预加载关联数据
$data['product'] = Product::with('attributes')->find($request['id']);
查询完成后直接通过$data['product']->attributes即可获取该产品对应的全部属性集合,产品基础信息和属性数据完全分离,无冗余。
方案2:手动处理JOIN查询结果
如果坚持使用原生JOIN写法,可以对返回的结果集做二次处理,合并重复的产品基础信息、归集所有属性:
$rawList = Product::select( 'products.*', 'product_attributes.id as attr_id', 'product_attributes.name as attr_name', 'product_attributes.value as attr_value' ) ->leftJoin('product_attributes', 'product_attributes.product_id', '=', 'products.id') ->where('products.id', $request['id']) ->get(); // 提取产品基础信息(取第一条的主表字段即可,所有行的主表数据都是重复的) $product = $rawList->first()?->only(['id', 'title', 'price' /* 此处补充你需要的products表所有字段 */]); // 归集所有非空的属性数据 $product['attributes'] = $rawList->filter(fn($item) => !is_null($item->attr_id)) ->map(fn($item) => [ 'id' => $item->attr_id, 'name' => $item->attr_name, 'value' => $item->attr_value ])->values(); $data['product'] = $product;
原写法问题说明
SQL左连接的特性就是主表每匹配到一条关联表数据,就会生成一行包含主表+对应关联表数据的结果,所以当一个产品对应3条属性时,自然会返回3行重复产品数据+单条属性的结果,你之前误以为只返回一条属性是因为只读取了第一行结果的属性字段,没有遍历所有行的属性部分。
内容的提问来源于stack exchange,提问作者stackoverflow account
相关产品推荐
相关产品推荐

