2016-01-13 40 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; 

    } 

}