2016-01-13 59 views
10

我有一个模型CourseModule,并且每个项目都与相同的模型有关。在同一模型上雄辩的亲子关系

数据库结构:

enter image description here

关系在型号:

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

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

我尝试以下,但它仅返回关系的一个级别。

尝试:

CourseModule::with('children')->get(); 

我试图创建类似下面的JSON输出,

预期输出:

[ 
    { 
    "id": "1", 
    "parent_id": "0", 
    "course_id": "2", 
    "name": "Parent", 
    "description": "first parent", 
    "order_id": "1", 
    "created_at": "-0001-11-30 00:00:00", 
    "updated_at": "-0001-11-30 00:00:00", 
    "children": [ 
     { 
     "id": "2", 
     "parent_id": "1", 
     "course_id": "2", 
     "name": "Child 1", 
     "description": "child of parent", 
     "order_id": "2", 
     "created_at": "-0001-11-30 00:00:00", 
     "updated_at": "-0001-11-30 00:00:00", 
     "children": [ 
      { 
      "id": "3", 
      "parent_id": "2", 
      "course_id": "2", 
      "name": "Child2", 
      "description": "child of child1", 
      "order_id": "2", 
      "created_at": "-0001-11-30 00:00:00", 
      "updated_at": "-0001-11-30 00:00:00", 
      "children": [ 
       { 
       "id": "4", 
       "parent_id": "3", 
       "course_id": "2", 
       "name": "Child 3", 
       "description": "child of child 2", 
       "order_id": "2", 
       "created_at": "-0001-11-30 00:00:00", 
       "updated_at": "-0001-11-30 00:00:00", 
       "children": [] 
       } 
      ] 
      } 
     ] 
     } 
    ] 
    } 
] 

我不明白怎么弄内子对象。

回答

3

如果你有这样的未知深度,你将不得不递归地获得孩子。

另一种选择是使用嵌套集合模型代替邻接表模型的。对于Laravel,您可以使用类似baum/baum包的嵌套集合。

“嵌套集是实现允许快速非递归查询的有序树的智能方法。” - https://github.com/etrepat/baum

有了这个包,你有一个像getDescendants方法来获取所有儿童和嵌套子和toHierarchy得到一个完整的树状分层结构。

Wikipedia - Nested Set Model

Baum - Nested Set pattern for Laravel's Eloquent ORM

Managing Hierarchical Data in MySQL

+0

嗨,'CourseModule :: whereId($ ID) - >第一个() - > getDescendantsAndSelf() - > toHierarchy()'只返回单个节点,我应该有对模型的任何变化,我正在用顶部 –

+0

中显示的单个表格工作谢谢@lagbox,它工作:) –

4

here是答案,可以帮助你

我想你,你必须这样做递归检索整个树:

$data = CourseModule::with('child_rec'); 

递归函数

这可以根据你的要求帮你,

public function child() 
{ 
    return $this->hasMany('App\CourseModule', 'parent'); 
} 
public function children_rec() 
{ 
    return $this->child()->with('children_rec'); 
    // which is equivalent to: 
    // return $this->hasMany('App\CourseModule', 'parent')->with('children_rec); 
} 
// parent 
public function parent() 
{ 
    return $this->belongsTo('App\CourseModule','parent'); 
} 

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

你应该在父母的关系

与使用(“孩子”)在孩子们的关系 与(“父”)

为您的代码是递归

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

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

注意:请确保您的代码有一些或其他退出合作如果不是这样,它会以永无止境的循环结束。

+0

它的工作原理!在第一个集合中,我有一棵链式树,但在同一个孩子中重复作为父集合。我不希望孩子再次作为根集合。有没有解决办法,或者我做错了? –

+0

找到解决方案'$ data = CourseModule :: with('children') - > where('parent_id',0)' –

1

您可以随时创建自己的递归函数,在我的情况下,我按照以下代码进行操作。

<?php 
declare(strict_types=1); 

namespace App\Models; 

use Illuminate\Database\Eloquent\Model; 
use Akmeh\Uuid; 

/** 
* Class Location 
* @package Domain\Models 
*/ 
class Location extends Model 
{ 
    use Uuid; 

    /** 
    * Indicates if the IDs are auto-incrementing. 
    * 
    * @var bool 
    */ 
    public $incrementing = false; 
    public $timestamps = false; 

    /** 
    * @param string $id 
    * @param array $tree 
    * @return array 
    */ 
    public static function getTree(string $id, array $tree = []): array 
    { 
     $lowestLevel = Location::where('id', $id)->first(); 

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

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

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

     return $tree; 

    } 

}