eloquent - 查询生成器中的动态和条件 whereHas()

eloquent - dynamic and conditional whereHas() in the query builder

我试图在我的查询构建器中避免 DRY,特别是在链中添加额外的方法。

例如,这最初是我拥有的查询构建器:

$products = $app->myShop->realProducts()
        ->where($query)
        ->skip($skip)->take($take)
        ->orderBy($sortKey, $sortOrder)
        ->get();

然后如果用户使用了一些过滤器,我需要将一个方法(特别是 whereHas())附加到查询构建器

    $products = $app->myShop->realProducts()
        ->where($query)
        ->whereHas('colour', function ($q) use ($find) {
            $q->where('colour_slug', $find);
        })
        ->skip($skip)->take($take)
        ->orderBy($sortKey, $sortOrder)
        ->get();

我发现 "ugly" 要实现此结果,我必须不断重复这些构建器查询:

if ($user_filtered_this_page == TRUE) {

    $products = $app->myShop->realProducts()->where($query)
        ->whereHas('colour', function ($q) use ($find) {
            $q->where('colour_slug', $find);
        })
        ->skip($skip)->take($take)
        ->orderBy($sortKey, $sortOrder)
        ->get();

} else {

    $products = $app->myShop->realProducts()->where($query)
        ->skip($skip)->take($take)
        ->orderBy($sortKey, $sortOrder)
        ->get();
}

是否有更聪明或更优雅的方式动态和有条件地将 whereHas() 方法追加到链中?

希望有人能提供帮助。谢谢!

你可以这样写:

$products = $app->myShop->realProducts()->where($query)
            ->whereHas('colour', function ($q) use ($find) {
                if ($user_filtered_this_page) {
                $q->where('colour_slug', $find);
            }
            })
            ->skip($skip)->take($take)
            ->orderBy($sortKey, $sortOrder)
            ->get();

希望对您有所帮助 ;)

查询在您调用 ->get() 之前不会执行,因此您可以非常简单地构建查询,有条件地添加 ->whereHas() 然后执行它:

$query= $app->myShop->realProducts()
    ->where($query)
    ->skip($skip)->take($take)
    ->orderBy($sortKey, $sortOrder);

if (...) {
    $query->whereHas(...);
}

$products = $query->get();

这可以使用 Query Builder Conditional Clauses

来完成
    $products = $app->myShop->realProducts()
        ->where($query)
        ->when($user_filtered_this_page, function($query) use($find){
            $query->whereHas('colour', function ($q) use ($find) {
                $q->where('colour_slug', $find);
            })
        })
        ->skip($skip)->take($take)
        ->orderBy($sortKey, $sortOrder)
        ->get();