Laravel查询生成器,根据条件在哪里?

时间:2019-07-18 07:41:45

标签: php mysql laravel query-builder

我有一个下拉列表来选择一个父对象,它是自引用页面的。我想限制该下拉菜单的结果,以免我将一个页面嵌套多个级别。

如果我编辑“儿子”页面,并且“儿子”具有“孙子”,则不应允许我选择“爸爸”作为儿子的父母,因为这会创建一个嵌套的深

在以下情况下,当我编辑Son记录时,由于儿子有孩子,所以我不应该选择Dad作为其父母。

+----+-----------+----------+
| id | parent_id |  title   |
+----+-----------+----------+
|  1 | NULL      | Dad      |
|  2 | NULL      | Son      |
|  3 | 2         | Grandson |
+----+-----------+----------+

现在,在这种情况下,我在编辑Son记录时应该可以选择爸爸作为父母,因为Son没有任何孩子

+----+-----------+----------+
| id | parent_id |  title   |
+----+-----------+----------+
|  1 | NULL      | Dad      |
|  2 | NULL      | Son      |
|  3 | NULL      | Grandson |
+----+-----------+----------+

我正在努力解决这个问题,以及如何在查询构建器中包装所有内容。

到目前为止我有什么

如果儿子有自己的孩子,以下代码将起作用,我将无法选择父亲,这很好。但是,如果没有孩子,它就会失败。

这归结为:我的父选择还应该允许显示parent_id为null的页面,但前提是当前记录(Son)没有任何子代。

回顾:仅在未在任何parent_id中出现该记录时才显示该记录,因此它没有子级,但如果没有,则不显示任何记录。如果没有,则应显示在parent_id为的记录空值。一个查询有可能吗?

$query->where('id', '<>', $page->id);
$query->where('parent_id', '<>', $page->id);

4 个答案:

答案 0 :(得分:1)

您需要自行连接表,因为按行是每行的基础。

使用左联接将表自身联接,其ID与父ID匹配。然后,仅选择联接表的ID为空的行。

$pages = DB::table('pages AS p')
            ->leftJoin('pages AS p1', 'p.id', '=', 'p1.parent_id')
            ->where('p.id', '<>', $page->id)
            ->whereNull('p1.id')
            ->select('p.*')
            ->get();

答案 1 :(得分:1)

您可以使用带有whereRaw函数的查询构建器子查询来实现此目的 检查代码

$result = DB::table('parents as p')
    ->whereRaw("parent_id is null and id not in (SELECT parent_id FROM parents WHERE parent_id is not null)")
    ->get();
dd($result);

o / p看起来像这样
第一种情况

enter image description here

第二种情况 enter image description here

它可能会帮助您:)

答案 2 :(得分:0)

嗯...我认为不可能将其仅打破一行,因为就像您将不得不循环检查parent_id列是否在parent_id列中一样:

但不必担心:使用不同的方法会更容易:两个单独的表,因此关系也不同:

Pages model: has one parent
Parents model: belongs to a page

通过以上关系,您可以轻松地通过雄辩地通过仅检查不存在给定关系的地方来获得没有父母的东西:

打破这一点:

Pages model:

public function parents () {
    return $this->hasOne(Parent::class, 'page_id');
}

对于父母模型:

 Parents model:

 protected $fillable = ['page_id'];

 public function pages () {
     return $this->belongsTo(Page::class, 'page_id');
 }

答案 3 :(得分:0)

您可以在Page模型中创建父子关系。

public function parent()
{
    return $this->belongsTo('Page', 'parent_id');
}

public function children()
{
    return $this->hasMany('Page', 'parent_id');
}

现在,您可以检查Page是否有子级,并选择父ID为null的记录,如下所示:

$pages = Page::where('parent_id', null)->doesntHave('children')->get();

这将为您提供父ID为null且没有子代的记录。希望你能理解。