Laravel中实现Serie下公共Product Property的关联查询方案
Laravel实现获取Serie下所有Product共有的Property
1. 确认模型关联定义
先确保三个模型的关联关系正确配置:
Serie 模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Serie extends Model { // 关联到所属的多个Product public function products() { return $this->hasMany(Product::class); } // 定义关联到Product的Property的查询入口 public function productProperties() { return $this->products() ->select('properties.*') ->join('product_property', 'products.id', '=', 'product_property.product_id') ->join('properties', 'product_property.property_id', '=', 'properties.id') ->groupBy('properties.id'); } }
Product 模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Product extends Model { // 关联到所属的Serie public function serie() { return $this->belongsTo(Serie::class); } // 多对多关联到Property,带中间表字段filterable public function productProperties() { return $this->belongsToMany(Property::class)->withPivot('filterable'); } }
Property 模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class Property extends Model { // 多对多关联到Product public function products() { return $this->belongsToMany(Product::class)->withPivot('filterable'); } // 定义本地作用域,筛选当前Serie下所有Product共有的属性 public function scopeSame(Builder $query) { // 从当前查询中提取serie_id条件 $serieId = collect($query->getQuery()->wheres) ->firstWhere('column', 'products.serie_id')['value'] ?? null; if (!$serieId) { throw new \RuntimeException('当前查询未关联到具体Serie'); } // 用子查询替代两次查询,一次SQL完成统计 return $query->havingRaw( 'COUNT(DISTINCT products.id) = (SELECT COUNT(*) FROM products WHERE serie_id = ?)', [$serieId] ); } }
2. 调用方式
现在可以直接通过链式调用获取目标属性集合:
$serie = Serie::find($serieId); $commonProperties = $serie->productProperties()->same()->get();
3. 注意事项
- 如果开启了MySQL严格模式,
groupBy需要包含properties表的所有字段,或者修改select语句明确列出所有需要的字段(例如select('properties.id', 'properties.name', ...))。 - 若不需要抛出异常,可以在
scopeSame中返回空查询集合,避免报错。
内容的提问来源于stack exchange,提问作者Erik-Jan
相关产品推荐
相关产品推荐

