首页 > 解决方案 > Laravel Eloquent - 过滤关系

问题描述

我的 Laravel 项目中有两个主要模型。ProductMaster 是主要产品数据所在的位置,而 Product 是保存每个产品的变化和每个客户的价格的模型。我不允许更改此模型,以防您想知道。

我的问题是如何进行雄辩的查询以获取 ProductMaster 数据,其中包含由客户端(以及其他参数)过滤的产品。我试过 whereHas 但它没有用。

这是我的模型:

namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class ProductMaster extends Model
{
    protected $table = 'product_masters';

    protected $primaryKey = 'id';

    protected $fillable = ['code','title'];
    
    public function products(){
        return $this->hasMany(Product::class,'master_id');
    }
}


namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\ProductMaster;

class Product extends Model
{

    protected $table = 'products';
    protected $primaryKey = 'id';

    protected $fillable = ['sku', 'stock', 'brand', 'size', 'priceList', 'master_id', 'client'];

    public function productMaster(){
        return $this->belongsTo(ProductMaster::class,'master_id');
    }

}

这是我试图做的查询:

        //QUERY WITH FILTERS
        $products = ProductMaster::whereHas('products', function($query) 
            use($filterBrand, $filterCats, $filterSizes, $clientCode)
            {
                $query->where('client', $clientCode);
                $query->whereIn('brand', $filterBrand);
                $query->whereIn('size', $filterSizes);
            })
        ->where('title', 'LIKE', '%' . $request->find . '%')
        ->orderby($order[0], $order[1])
        ->paginate(6)
        ->withQueryString();

这个查询有效,但我没有得到我所需要的。这给了我所有具有具有该参数的产品的 ProductMaster,但是在集合 $products 中,它放置了具有该 master_id 的所有产品,而不仅仅是具有该参数的产品。

这是sql:

select * from `product_masters` where exists (select * from `products` where `product_masters`.`id` = `products`.`master_id` and `client` = ? and `products`.`brand` in (?) and `category` in (?) and `client` = ?) and `title` LIKE ? order by `title` asc

这是一些示例数据:SQL Fiddle

任何人都可以帮助我吗?谢谢。

标签: phplaraveleloquent

解决方案


如果您想过滤产品以预先加载,并且还过滤以仅加载拥有这些产品的产品主机,您的查询应该是这样的:


$products = ProductMaster::
with([
 'products' =>
 fn($query) => $query
 ->where('client', $clientCode)
 ->whereIn('brand', $filterBrand)
 ->whereIn('size', $filterSizes)
])
->whereHas('products', 
 fn($query) => $query
 ->where('client', $clientCode)
 ->whereIn('brand', $filterBrand)
 ->whereIn('size', $filterSizes)
)
        ->where('title', 'LIKE', '%' . $request->find . '%')
        ->orderby($order[0], $order[1])
        ->paginate(6)
        ->withQueryString();

您甚至可以将 with 和 whereHas 函数上的查询传递给控制器​​内部的私有函数,以保持克隆更干净。


推荐阅读