Laravel 7 雄辩的嵌套条件,用于使用枢轴进行过滤

Posted

技术标签:

【中文标题】Laravel 7 雄辩的嵌套条件,用于使用枢轴进行过滤【英文标题】:Laravel 7 eloquent nested conditions for filtering with pivot 【发布时间】:2021-06-27 18:17:31 【问题描述】:

我正在做一个项目,但陷入了困境。假设我有 4 张桌子;供应商、产品、category_products(枢轴)、类别。 假设每个表在下面都有这一列:

供应商 ID 姓名 等等

产品 ID 供应商 ID 姓名 股票 等等

category_products ID product_id 类别ID 时间戳

类别 ID 名字

型号: 供应商

    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 子句条件。我在这里做错了什么?

【问题讨论】:

【参考方案1】:

文档: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);
    
);

【讨论】:

感谢您的快速回复。但是,如果我使用急切加载,with() 之后的whereHas() 是否必要?【参考方案2】:

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

型号

产品

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。

注意:如果这段代码看起来“乱七八糟”,请告诉我,这样我和所有阅读本文的人都可以提高成为更好的程序员

【讨论】:

您本可以接受我的回答,我会根据您当前的解决方案对其进行编辑 我在卡住之前尝试了不同的组合。在您回答之前已找到此解决方案。我通过给你一个赞成票来感谢你的回答。但是您的解决方案不起作用,因为我已经这样做了。

以上是关于Laravel 7 雄辩的嵌套条件,用于使用枢轴进行过滤的主要内容,如果未能解决你的问题,请参考以下文章

如何使用父枢轴值作为条件获得雄辩的关系

Laravel Eloquent 嵌套关系枢轴与约束

Laravel 雄辩与条件

如何在 Laravel 雄辩关系中添加多个条件

Laravel 中的雄辩关系(7)

使用现有表模式上的数据透视表在雄辩模型中指定关系字段