我是一名初学 Laravel 的人,目前我非常喜欢 Eloquent 和 QueryBuilder,但是当查询变得更加复杂时,我的头脑就开始疼痛...经过相当长的时间,我刚完成了两个可行的示例,也许你们可以帮助我进行优化。首先我将给出这两个示例,然后分别说明它们的 (不)优点。
首先是 DB::select... 说实话,我认为这比第二个示例更可读...或者可能是我没有正确地使用构建器 xD。
$shared_slugs = Magic::in_query($this->shared_slugs);
$items = DB::select("
SELECT * FROM f_admin_items
WHERE
active = 1
AND (
slug IN $shared_slugs
OR
:treshhold <= :urank AND id IN (SELECT admin_item_id FROM f_user_access WHERE user_id = :uid)
OR
:treshhold > :urank AND `rank` >= :urank
)
ORDER BY `order` ASC
", [
'treshhold' => $this->threshold_rank,
'urank' => $user_rank,
'uid' => $user_id
]);
总体而言,使用命名参数绑定非常有效。基本上,菜单项始终必须处于活动状态,加上(1或2或3)。例如,dashboard 被接受为共享 slug。否则,会进行一些排名检查。
现在我一直在努力尝试使用 eloquent en query builder =/ 实现此目的。我认为设置关系不是必要的,���为我只在菜单和中间件中使用它。在这种情况下,f_user_access 表仅包含 admin_item_id 和 user_id,不真正充当枢轴,并且在其他任何地方都没有使用。
$items =
$this->where( 'active', 1 )
->where( function ($query) {
$query->whereIn( 'slug', $this->shared_slugs )
->orWhere(function ($query) {
$query->whereRaw( $this->threshold_rank.' <= '.$this->user_rank )
->whereIn('id', function ($query) {
$query->select('admin_item_id')->from('f_user_access')->where('user_id', $this->user_id)->get();
});
})
->orWhere(function ($query) {
$query->whereRaw( $this->threshold_rank.' > '.$this->user_rank )
->where( 'rank', '>=', $this->user_rank );
});
})->orderBy( 'order', 'ASC' )->get();
我喜欢第二个的原因是我可以将$shared_slugs作为一个数组传递,而不必先将其转换为字符串。但除此之外,我真的讨厌这种写法,例如where(function($query){})等等...另外,传递给该函数的$ids,在where.functions中无法访问,所以我必须先在类中定义它们。
第一个我喜欢因为有命名绑定且不那么难读,变量也是可以访问的...缺点是我必须调用这个函数将共享slug转换为一个数组。
不使用Eloquent和QueryBuilder真的很糟糕吗?至少在某些情况下...你们会怎么做才能使第二个示例更好呢?=/
更新:由于回答和反馈,我放弃了原始SQL。当前函数中有5个范围,并且一个(小)模型用于user_access。
$items =
$this->active() //Only active items AND... 1, 2 or 3
->where( function ($query) {
$query->shared_slug() // 1
->orWhere(function ($query) { // OR 2
$query->access_required()
->whereIn('id', UserAccess::get_access( $this->user_id ) );
})
->orWhere(function ($query) { // OR 3
$query->no_access_required()
->whereRaw( 'rank >= '.$this->user_rank );
});
})->ASC()->get();
whereRaw()
代替->where(attribute, operator, value)
。 - KyslikscopeDesc
和scopeAsc
。 - Kyslik