如何循环通过这些树? laravel php嵌套集递归(相同模型)

时间:2018-03-31 08:29:08

标签: php laravel nested set

如何在laravel中循环遍历此树节点? 我花了几天时间才开始工作,但事实并非如此! 这是表结构:

id        parent_id        text;
1         0                parent;
2         1                child;
3         2                descendant;
4         0                parent;

` 等等......

这是模型关系

public function parent()
{
    return $this->belongsTo('App\ContextMenuItem','parent_id')->where('parent_id',0);
}

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

以下是我不知道如何使用它来递归获取项目的功能。

public static function getTree(string $id, array $tree = []): array
{
    $lowestLevel = ContextMenuItem::where('id', $id)->first();

    if (!$lowestLevel) {
        return $tree;
    }

    $tree[] = $lowestLevel->toArray();

    if ($lowestLevel->parent_id !== 0) {
        $tree = ContextMenuItem::getTree($lowestLevel->parent_id, $tree);
    }

    return $tree;

}

2 个答案:

答案 0 :(得分:0)

我认为主要问题在于您的关系定义:

public function parent()
{
    return $this->belongsTo('App\ContextMenuItem','parent_id')->where('parent_id',0);
}

->where('parent_id', 0)会导致深度高于1的儿童出现问题,因为只有根父母的子女拥有parent_id = 0的父级。我还没有使用递归关系,但是从你的代码中我会说删除where并且你很高兴。

之后,您应该能够在查询中加载with('children')的所有孩子。

答案 1 :(得分:0)

我举例说明了文章的工作代码。在App \ Article.php中

public function parent()
{
    return $this->belongsTo(Article::class, 'master_id', 'id');
}
public function children()
{
    return $this->hasMany(Article::class, 'master_id', 'id');
}

ArticleController.php

$articles = Article::where('master_id', 0)->orderBy(...)->paginate();
文章/ index.blade.php中的

@foreach($articles as $article)
    @include('articles.article_item_well', ['recursive' => true])
@endforeach
处理标准输出后

和articles / article_item_well.blade.php

@if ($recursive && $article->children()->count() > 0)
<div class="panel-body">
    @foreach($article->children as $article)
        @include('articles.article_item_well')
    @endforeach
</div>
@endif

它的美妙之处在于你可以称之为递归与否。它可以处理无数个孩子。在某些情况下,比如搜索结果,您宁愿没有递归结果。然后,您将where('master_id', 0)放在搜索功能结果对象和视图['recursive' => false]中。

添加:我承认paginate()确实占用了15个顶级记录,但它无法控制子级数。在我看来,这不是什么大不了的事。如果这对您很重要,我相信它可以在数据库级别完成。但遗憾的是,无论是原始SQL还是雄辩,我无法帮助您。我在一个例子中看过一次SQL命令,它的复杂性高于我对(My)SQL的了解。