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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 12:44:54