Laravel中的递归自连接

Laravel中的递归自连接,laravel,eloquent,self-join,Laravel,Eloquent,Self Join,我有下表: | node_id | node_name | parent_id | | 1 | Node 1 | | | 2 | Node 2 | 1 | | 3 | Node 3 | 1 | | 4 | Node 4 | 2 | 我希望递归地检索特定节点下的所有节点 我的模型如下所示: class Tree extends Model {

我有下表:

| node_id | node_name | parent_id |  
| 1       | Node 1    |           |  
| 2       | Node 2    | 1         |  
| 3       | Node 3    | 1         |  
| 4       | Node 4    | 2         |
我希望递归地检索特定节点下的所有节点

我的模型如下所示:

class Tree extends Model
{
    public function parent()
    {
        return $this->belongsTo(self::class, 'node_id');
    }

    public function children()
    {
        return $this->hasMany(self::class, 'parent_id', 'node_id');
    }

    public function allchildren()
    {
        return $this->hasMany(self::class, 'parent_id', 'node_id')->with('allchildren');;
    }
}
现在,如果要检索节点的所有子体,请执行以下操作:

$node = Tree::where('node_id', 1)->first();
$nodes = $node->allchildren;
        
然而,上面的代码只返回第一级,而忽略了更深层次的子级

我做错了什么

编辑

事实上,我现在明白了,实际上我正在正确地检索所有数据,只是我看到了输出数组的顶层

问题是如何将输出展平,以在单个数组中显示数据

编辑2

因此,我设法创建了一个函数,使用以下代码(例如在控制器中)将输出平坦化为一级数组:

然后这样称呼它:

$flatTree = $this->flattenTree($nodes);

在我的脑海里,我想你可以用这样的东西来实现这一点

public function allChildren()
{
    $nodes = collect();
    $this->children->each(function($node) use ($nodes){
      $nodes->push($node);
      $nodes = $nodes->merge($node->allChildren()); //merge this node's children
    });
    return $nodes;
}
基本上,逻辑是为每个
子节点
调用
所有子节点
,并创建一个新的节点集合。这种特殊逻辑的缺点是,它将在一个级别集合中获取所有节点。

您可以使用
with()
进行操作。所以看起来像

Tree::where('node_id', 1)->with('allchildren')->get();
您也可以进行嵌套加载

Tree::where('node_id', 1)->with('children.children')->get();

with
将执行一次
选择(如果存在)
。它不是递归操作。您可以考虑在子集合上执行一些逻辑来获取所有节点。谢谢,这实际上是可行的,但是我如何才能展平输出的输出?@Lamar I'm高兴:)因为它返回一个雄辩的集合,所以您可以使用它来进一步操纵输出。有一个方法,但我不确定它是否有用,因为您的节点可能有许多子节点,因此根据您的预期输出,您可能需要使用或其他方法。实际上,我需要的是在一个级别中获取所有子节点。基本上类似于表结构。但是这行的意思是什么:
$nodes=collect()正在打开新的空集合。你测试过这个代码吗?对不起,我是新来的。所以你的意思是我应该用这个方法替换我的关系,或者这是一个帮助器方法来平展输出或我的关系?你可以用它代替模型中的
allchildren
方法,或者把它作为一个新方法放在模型中,如果你对结果满意,你可以使用它。它不起作用。不确定如何调用此方法,无论是作为关系属性、抽象方法还是应将父节点作为参数传递?
Tree::where('node_id', 1)->with('children.children')->get();