[英]How can I build such a query using Laravel query builder?
有一张 MySQL “类别”的表格。
类别 model 具有如下所示的“hasMany”关系。
public function children(){
return $this->hasMany(self::class, 'parent_id');
}
在类别编辑页面上,为了将父类别分配给当前类别(为此我需要填写其 parent_id 字段),我必须生成一个 Select 标记,该标记将包含类别表中的所有行,除了当前一个及其所有子类别。
category_id | parent_id
------------------------
1 | NULL
2 | 1
3 | 2
4 | 3
5 | NULL
6 | 5
For example,
for category_id 1, should be selected lines with category_id [5, 6]
for category_id 2, should be selected lines with category_id [1, 5, 6]
for category_id 3, should be selected lines with category_id [1, 2, 5, 6]
for category_id 4, should be selected lines with category_id [1, 2, 3, 5, 6]
for category_id 5, should be selected lines with category_id [1, 2, 3, 4]
for category_id 6, should be selected lines with category_id [1, 2, 3, 4, 5]
如果一个category有parent_id是NULL,则表示它没有父category。
简短回答:您需要EXCEPT
所有记录,但当前类别中的递归记录除外。
对于递归部分,您可以使用: https://github.com/staudenmeir/laravel-adjacency-list
查看它默认包含的descendantsAndSelf()
关系。
接下来,您需要构建EXCEPT
查询。 查询生成器不包括除 function 之外的,因此您需要自己构建一个。
例如,我的一个控制器中有这个:
我有一个名为Thread
的 eloquent model ,它是一个用于保存消息线程的 model 。 人们对这些线程有不同的查看权限,所以我需要几个查询来过滤出他们可以看到和看不到的线程。
我使用元素查询构建器和一些 I UNION
预构建这些单独的查询。 比有一个明确排除线程的查询。 然后我结合了 unioned 和$excludeExplicit
查询:
$query = Thread::query()
->fromRaw(
'(SELECT * FROM ((' . $unioned->toSql() . ') EXCEPT ' . $excludeExplicit->toSql() . ') AS threads) AS threads',
array_merge($unioned->getBindings(), $excludeExplicit->getBindings())
);
(见https://stackoverflow.com/a/64231210/9258054 )
这个原始查询的技巧在于参数绑定的合并。 此外,此查询的结果是 Eloquent 模型。 请注意,在使用UNION
或EXCEPT
等查询时,您需要确保两者的SELECT
语句返回相同的列。
在代码中挖掘了一下之后,我找到了一个更优雅的解决方案。 我正在使用“文章”model 中创建的“类别”关系从数据库中进行选择
public function categories(){
return $this->morphToMany(Category::class, 'categoryable');
}
在这样做时,我只 select 那些没有父类别的项目。 但是由于“类别”关系,所有子项 go 到“Article”集合,并且项目树构建正确,我不必使用“Join”进行复杂的查询。
public function topMenu(){
View::composer('layouts.header', function ($view){
$view->with('categories', Category::whereNull('parent_id')->where('published', 1)->get());
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.