Laravel 7 eloquent 使用数据透视过滤的嵌套条件

Laravel 7 eloquent nested conditions for filtering with pivot

我正在做一个项目,遇到了一个问题。假设我有 4 table;供应商、产品、category_products(枢轴)、类别。 假设每个 table 下面都有此列:

型号: 供应商

    public function products(){
        return $this->hasMany('App\Models\Sewa\Products', 'vendor_id')->with('product_images');
    }

产品

    public function product_category(){
        return $this->hasOne('App\Models\Sewa\ProductCategories', 'product_id');
    }

产品类别

    public function category(){
        return $this->belongsTo('App\Models\Sewa\Categories', 'category_id');
    }

    public function product(){
        return $this->belongsTo('App\Models\Sewa\Products', 'product_id');
    }

类别

    public function product_category(){
        return $this->hasMany('App\Models\Sewa\ProductCategories', 'category_id');
    }

我试图按类别和价格过滤供应商的产品。但是每个产品只有一个类目,但是一个类目可以用在很多产品上。 我所做的是:

$vendors = Vendors::with('products.product_category.category')->whereHas('products', function($query) use($request){
    if($request->category !== 'all'){
        $query->whereHas('product_category', function($query) use($request){
            $query->where('category_id', $request->category);
        });
    }

    if($request->price === 'low'){
        $query->whereBetween('price', [0, 10000]);
    }

    if($request->price === 'middle'){
        $query->whereBetween('price', [10000, 250000]);
    }

    if($request->price === 'high'){
        $query->where('price', '>', 250000);
    }
});

我试图获取类别 id = 1,但我得到了完整的记录。我真的不知道为什么它会忽略 where 子句条件。我这里做错了什么?

文档:https://laravel.com/docs/8.x/eloquent-relationships#constraining-eager-loads

像这样使用你的关系约束:

$vendors = Vendors::with(['products.product_category.category' => function($request){
    // your condition
}])->whereHas('products', function($query) use($request){
    if($request->category !== 'all'){
        $query->whereHas('product_category', function($query) 
use($request){
             $query->where('category_id', $request->category);
        });
    }

    if($request->price === 'low'){
        $query->whereBetween('price', [0, 10000]);
    }

    if($request->price === 'middle'){
        $query->whereBetween('price', [10000, 250000]);
    }

    if($request->price === 'high'){
        $query->where('price', '>', 250000);
    }
});

感谢我的朋友,我得到了答案。所以基本上,它仍然是一个多对多的关系。如果我错了纠正我。我改变了几件事;

型号

产品

public function product_category(){
    return $this->hasMany('App\Models\Sewa\ProductCategories', 'product_id');
}

我将 hasOne() 更改为 hasMany(),但两者都完美无缺。但是在这种情况下,我的朋友告诉我使用多对多关系,即使每个产品只有一个类别。

控制器

$vendors = Vendors::with(['products' => function($query) use($request){
    if($request->category !== 'all'){
        $query->whereHas('product_category', function($query) use($request){
            $query->where('category_id', $request->category);
        });
    }

    if($request->price === 'low'){
        $query->whereBetween('price', [0, 10000]);
    }

    if($request->price === 'middle'){
        $query->whereBetween('price', [10000, 250000]);
    }

    if($request->price === 'high'){
        $query->where('price', '>', 250000);
    }
}, 'products.product_category.category']);

这个逻辑解决了我的问题。我没有首先使用 whereHas() ,而是像 @Psycho 提到的那样使用带有条件的预加载。感谢我的朋友和@Psycho。

注意:如果此代码看起来 'messy' 请告诉我,这样我和阅读此代码的每个人都可以改进成为更好的程序员。