简体   繁体   English

Laravel Eloquent从自引用表中获取N Level层次结构记录与其他表的列

[英]Laravel Eloquent get N Level hierarchy records from self-referencing table with other table's columns

I am using Laravel 4 with MySQL back-end. 我正在使用带有MySQL后端的Laravel 4

I have two database tables namely - surveyes and templates . 我有两个数据库表 - surveyestemplates

Both of the tables are self-referencing and they have column named parent that is foreign key of that table itself. 这两个表都是self-referencing ,它们具有名为parent column ,该column是该表本身的foreign key Their records are in self referencing parent-child relationship. 他们的记录是self referencing parent-child关系。

The table design is as below : 表格设计如下:

Surveyes : 调查对象:

(PK)                        (FK_Surveyes)
Id  title       type        parent          sort_order  deleted_at
1   General     group       NULL            1           NULL
2   Where..?    question    1               1           NULL
3   abc..       answer      2               1           NULL
4   def..       answer      2               2           NULL
5   efg..       answer      2               3           NULL
6   ghi..       answer      2               4           NULL
7   What..?     question    1               2           NULL
8   hij..       answer      7               1           NULL
9   ijk..       answer      7               2           NULL
10  How..?      question    8               1           NULL
11  jkl..       answer      10              1           NULL
12  mnm..       answer      10              2           NULL
13  Special     group       NULL            2           NULL
14  Whom..?     question    13              1           NULL
15  opq..       answer      14              1           NULL
16  rst..       answer      14              2           NULL

Templates: 模板:

(PK)(FK_surveyes)               (FK_Templates)
Id  survey_id       type        parent          sort_order  deleted_at
1   NULL            group       NULL            1           NULL
2   14              question    1               1           NULL
3   15              answer      2               1           NULL
4   16              answer      3               2           NULL
5   NULL            group       NULL            2           NULL
6   2               question    5               1           NULL
7   3               answer      6               1           NULL
8   4               answer      6               2           NULL
9   5               answer      6               3           NULL
10  6               answer      8               4           NULL
11  7               question    10              2           NULL
12  8               answer      10              1           NULL
13  9               answer      10              2           NULL

Now, I want their records also to be in the same manner with N level of hierarchy. 现在,我希望他们的记录也与N级别的层次结构相同。

So that I have creates a model for templates as below : 所以我为templates创建了一个model ,如下所示:

class Template extends BaseModel{

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

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

    // recursive, loads all descendants
    public function children()
    {
       return $this->child()->with('children')->orderBy('sort_order');
    }

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

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

And I am using method below (which is working fine) to get the N level of hierarchy for templates : 我正在使用下面的方法(工作正常)来获取模板的N级层次结构:

public function getTemplates(){
    $templates = Template::with('children')
                ->whereNull('parent')
                ->orderBy('sort_order', 'ASC');

    return $templates->toJson();
}

But now, I want the column title from the surveyes table. 但现在,我想要surveyes表中的列title The column survey_id in table templates is the foreign key of table surveyes . survey_idtemplatesforeign key表的surveyes

How can I achieve it? 我怎样才能实现它?

I have updated following method in Template model as below : 我在Template模型中更新了以下方法,如下所示:

public function children()
{
   return $this->child()->with('children')->orderBy('sort_order')
        ->leftJoin('surveyes', 'surveyes.id', '=', 'templates.survey_id')->select('templates.*','surveyes.title');
}

But it doesn't gives the hierarchical records and browser gets hang-up . 但它没有给出分层记录和浏览器挂起 I have only 1500 records in templates table. 我在templates表中只有1500条记录。

Does anybody knows how to achieve it? 有谁知道如何实现它?

EDIT : 编辑:

I have added a method to get Survey model in templates as below : 我添加了一个方法来获取模板中的Survey模型,如下所示:

public function survey()
    {
        return $this->belongsTo('D2D\Models\Survey','survey_id');
    }

and updated the children() method as below : 并更新了children()方法,如下所示:

public function children()
{
   return $this->child()
   ->with('survey','children')
   ->orderBy('sort_order');
}

Now I am able to get the records of Survey model but it returns all the column of the Survey as below : 现在我能够得到的记录Survey的模式,但它返回的所有列的Survey如下:

{
    "id": 2,
    "survey_id": 522,
    "title": "Abc....?",
    "type": "question",
    "parent": 1200
    "survey": {
        "id": 522,
        "type": "question",
        "subtype": null,
        "title": "Abc....?",
        "parent": 1
    },
    "children": [{
        "id": 3,
        "survey_id": 526,
        "title": "aaa",
        "type": "answer",
        "parent": 2
        "survey": {
            "id": 526,
            "type": "answer",
            "subtype": null,
            "title": "aaa",
            "parent": 522
        },
        "children": []
    },
    {
        "id": 4,
        "survey_id": 527,
        "title": "bbb",
        "type": "answer",
        "parent": 2
        "survey": {
            "id": 527,
            "type": "answer",
            "title": "bbb",
            "parent": 522,
        },
        "children": []
    },
    ...
}

But I want it like below : 但是我想要它如下:

{
    "id": 2,
    "survey_id": 522,
    "title": "Abc....?", // Must be from Survey table
    "type": "question",
    "parent": 1200
    "children": [{
        "id": 3,
        "survey_id": 526,
        "title": "aaa", // Must be from Survey table
        "type": "answer",
        "parent": 2
        "children": []
    },
    {
        "id": 4,
        "survey_id": 527,
        "title": "bbb", // Must be from Survey table
        "type": "answer",
        "parent": 2
        "children": []
    },
    ...
}

Is there any way to achieve this? 有没有办法实现这个目标?

I have tried by updating survey() method as below : 我尝试过更新survey()方法,如下所示:

public function survey()
{
    return $this->belongsTo('D2D\Models\Survey','survey_id')->select(array('title'));
}

But in that case it gives title=NULL for each and every element. 但在这种情况下,它为每个元素赋予title = NULL。

Please let me know how to achieve this? 请告诉我如何实现这一目标?

Thanks. 谢谢。

One possible solution to this problem is to use the Nested Sets model. 此问题的一种可能解决方案是使用嵌套集模型。 This avoids the problem of recursive queries. 这避免了递归查询的问题。 There are two available Laravel packages that extend Eloquent to implement Nested Sets: Laravel-NestedSet and Baum . 有两个可用的Laravel包扩展了Eloquent来实现嵌套集: Laravel-NestedSetBaum I understand you have the issue of existing data; 我知道你有现有数据的问题; however, it shouldn't be too hard to make a one-time migration script. 但是,制作一次性迁移脚本应该不会太难。 You can create new models using whichever nested sets library you pick; 您可以使用您选择的任何嵌套集库创建新模型; these models will have methods to set the parent node of a survey. 这些模型将具有设置调查的父节点的方法。 You can have the new survey data in a new table (you can override the table name in Eloquent; see here. Then, write a script or protected controller action to migrate the existing surveys to the new table. It will work something like this (using the laravel-nestedset syntax; Baum is similar): 您可以将新的调查数据放在新表中(您可以在Eloquent中覆盖表名; 请参阅此处。然后,编写脚本或受保护的控制器操作以将现有调查迁移到新表。它将起到这样的作用(使用laravel-nestedset语法; Baum类似):

$oldSurveys = Survey::all();
$oldSurveys->each(function($survey) {
    $newSurvey = NestedSurvey::create(array($survey->name, $survey->type ...etc));
});

$newSurveys = NestedSurvey::whereNotNull('parent_id');
$newSurveys->each(function($survey) {
    $parent = NestedSurvey::find($survey->parent_id);
    $survey->appendTo($parent)->save();
});

Once you have imported all your survey into the new table, you can switch your application over to use the new models. 将所有调查导入新表后,可以切换应用程序以使用新模型。

Now, you'll be able to fetch an arbitrarily deep hierarchy in linear time. 现在,您将能够在线性时间内获取任意深度的层次结构。 And since your model extends Eloquent, you can get any related columns just as you normally would. 由于您的模型扩展了Eloquent,您可以像平常一样获得任何相关列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM