来自自引用表的 Laravel ORM 获得 N 级层次结构 JSON

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24672629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 09:47:47  来源:igfitidea点击:

Laravel ORM from self referencing table get N level hierarchy JSON

phplaravellaravel-4

提问by Dev

I am using LARAVEL 4with MySQLback-end.

我使用LARAVEL 4MySQL后端。

I have a self-referencingtable with columns id, name, typeand parent. Here, parentis foreign-keyof the column Id. The data in table is as below :

我有一个self-referencing带有列id, name, typeparent. 这里,parentforeign-keyId。表中数据如下:

id  name          type         parent 
1   General       group        NULL
2   What is..?    question     1
3   aa            answer       2
4   bb            answer       2
5   cc            answer       2
6   How is..?     question     1
7   ba            answer       6
8   bb            answer       6
9   Where is..?   question     4
10  ca            answer       9
11  cb            answer       9
12  Who is..?     question     6
13  da            answer       12
14  db            answer       12
15  Specific      group        NULL
16  When is..?    question     15
17  ea            answer       16
18  eb            answer       16
19  Whome is..?   question     2
20  fa            answer       19
21  fb            answer       19
22  fc            answer       19

I want a function that return nested JSONusing this relational data. For example :

我想要一个nested JSON使用此关系数据返回的函数。例如 :

[{
  "id" : 1, 
  "name" : "Geneal", 
  "type" : "group", 
  "children" : [{
      "id" : 2, 
      "name" : "What is..?", 
      "type" : "question", 
      "children" : [{
         "id" : 3, 
         "name" : "aa", 
         "type" : "answer"
      },
      {
         "id" : 4, 
         "name" : "bb", 
         "type" : "answer"
      },
      {
         "id" : 5, 
         "name" : "cc", 
         "type" : "answer"
      }]},
      {
      "id" : 6, 
      "name" : "How is..?", 
      "type" : "question", 
      "children" : [{
         "id" : 7, 
         "name" : "ba", 
         "type" : "answer"
      },
      {
         "id" : 8, 
         "name" : "bb", 
         "type" : "answer"
      }]
   }]
... and so on
}]

I have created a modelnamed Surveyas below :

我创建了一个model命名Survey如下:

class Survey extends BaseModel{

    protected $table = 'questions';
    protected $softDelete = false;

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

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

and called it in controllerwith :

并调用它controller

$user = Survey::all();
$parent = $user->parent()->first();
$children = $user->children()->get();

But I am not getting the proper result as I have mentioned in JSONabove.

但是我没有得到JSON上面提到的正确结果。

print_r($parent->toJson()); 

gives records with one level hierarchy only (i.e group and questions, not answers).

仅提供具有一级层次结构的记录(即组和问题,而不是答案)。

while

尽管

print_r($children ->toJson());

Gives only questions (Not groups and answers).

只给出问题(不是分组和答案)。

I want the whole self-referencing data in nested JSON format with N level of hierarchy.

我想要嵌套 JSON 格式的整个自引用数据,具有 N 级层次结构

I also have tried

我也试过

$user = Survey::with('parent', 'children')->get();

But found same as $parent above.

但发现与上面的 $parent 相同。

Is there anyway I can get the desired result?

无论如何我能得到想要的结果吗?

Thanks in advance..

提前致谢..

回答by Jarek Tkaczyk

Here's how you manually retrieve nested relations:

以下是手动检索嵌套关系的方法:

$collection = Model::with('relation1.relation2.relation3')->get();

So in your case it would be:

所以在你的情况下,它将是:

$surveys = Survey::with('children.children.children')->get();

Obviously this will do the job when the relations are fixed, but it's not the way to go for a recursive relation to the same table.

显然,当关系固定时,这将完成工作,但这不是对同一张表建立递归关系的方法。

Fortunately, you can make such relation recursive, then all you need to retrieve whole tree is this:

幸运的是,你可以使这种关系递归,那么你需要检索整个树是这样的:

$surveys = Survey::with('childrenRecursive');

However, I wouldn't load parent for each row this way.

但是,我不会以这种方式为每一行加载父级。

So here's all you need:

所以这就是你所需要的:

// Survey model
// loads only direct children - 1 level
public function children()
{
   return $this->hasMany('Survey', 'parent');
}

// recursive, loads all descendants
public function childrenRecursive()
{
   return $this->children()->with('childrenRecursive');
   // which is equivalent to:
   // return $this->hasMany('Survey', 'parent')->with('childrenRecursive);
}

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

// all ascendants
public function parentRecursive()
{
   return $this->parent()->with('parentRecursive');
}


EDIT: To get real tree structure, first query must be limited to only root nodes:

编辑:要获得真正的树结构,第一次查询必须仅限于根节点:

$surveys = Survey::with('childrenRecursive')->whereNull('parent')->get();

回答by ??????? ????

so simple!!!

很简单!!!

1- load your 'children' relation in your 'children' relation in your model like this :

1- 像这样在模型中的“孩子”关系中加载“孩子”关系:

class Survey extends BaseModel{

    protected $table = 'questions';
    protected $softDelete = false;

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

    public function children()
    {
       // change this: return $this->hasMany('Survey', 'parent');

        return $this->hasMany('Survey', 'parent')->with('children);
    }   
}

2- you just need add clouserfunction to your relation like this:

2- 你只需要像这样向你的关系添加clouser函数:

$surveys = Survey::with(['children' => function($q) {
            $q->with('children');
       },
       'parent' => function($q) {
            $q->with('parent');
       });

then you can access to your nested children in your result like this:

然后您可以像这样访问结果中的嵌套子项:

$surveys->children

and unlimited nesting :

和无限嵌套:

$surveys->children->first()->children

and so on.

等等。