基本上,我尽可能地遵循胖模型和瘦控制器的原则。我想出了这个想法: 在我网站上的许多页面上,我想加载我所有的产品,但我想指出我想要加载的关系,因为我并不总是需要它们。 这是我支持的函数,如果我将任何参数设置为 true,它会急切地加载该关系,以便我尽可能高效地进行查询。
public static function getProducts($brand = null, $categories = null, $image = null, $images = null, $tags = null, $ratings = null, $attributes = null)
{
$query = Product::query();
if ($brand) {
$query->whereHas('brand', $brand = function ($query) {
$query->where('active', 1);
})->with('brand', $brand);
}
if ($image) {
$query->whereHas('images', $images = function ($query) {
$query->where('active', 1)->where('main', 1);
})->with('images', $images);
}
if ($images) {
$query->whereHas('images', $images = function ($query) {
$query->where('active', 1);
})->with('images', $images);
}
if ($tags) {
$query->whereHas('tags', $tags = function ($query) {
$query->where('active', 1);
})->with('tags', $tags);
}
if ($categories) {
$query->whereHas('categories', $categories = function ($query) {
$query->where('active', 1);
})->with('categories', $categories);
}
if ($ratings) {
$query->whereHas('ratings', $ratings = function ($query) {
$query->where('active', 1);
})->with('ratings', $ratings);
}
if ($attributes) {
$query->whereHas('attributes', $attributes = function ($query) {
$query->where('active', 1);
})->with('attributes', $attributes);
}
return $query;
}
我不知道所有 whereHas() 是否都像我想象的那样高效,因为每次我急切加载关系时它都像 1 个子查询一样。 这解决了我必须在控制器中一直执行 ->with() 的问题,但想象一下我还想按特定类别或几个类别进行过滤。 我可以为此使用范围吗? 假设我只想获得活性产品,我可以在模型中创建这个函数:
public function scopeActive($query)
{
return $query->where('active', 1);
}
拿到我的产品后这样称呼它:
$query = Product::getProducts(false, false, false, false, false, false, false)
$query->active();
或者,如果我想按类别过滤,我可以在产品模型中创建此函数:
public function scopeCategories($query, $categories)
{
$query->with(['categories' => function ($query) use ($categories) {
$query->whereIn('categories', $categories);
}]);
return $query;
}
然后再次调用它以过滤仅属于那些类别/类别的产品。
$query->categories($categoryIds);
我正在模型中完成所有这些工作,因此我可以从控制器调用该函数 1 次,预先加载我想要的关系,然后按我需要的进行过滤。但我不知道这是否是最好的方法。这是正确的做法吗?
我正在努力进入中级水平,并且尝试抽象一切比我想象的更难。
提前致谢!