【问题标题】:Eloquent Parent-Child relationship on same model同一模型上的雄辩父子关系
【发布时间】:2016-04-17 23:18:49
【问题描述】:

我有一个型号CourseModule,每一项都和同一个型号相关。

数据库结构:

模型中的关系:

    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": []
              }
            ]
          }
        ]
      }
    ]
  }
]

我不明白如何获取内部子对象。

【问题讨论】:

    标签: php laravel laravel-5 eloquent laravel-5.1


    【解决方案1】:

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

    另一种选择是使用嵌套集模型而不是邻接列表模型。你可以使用类似 baum/baum 的 Laravel 包来构建嵌套集。

    “嵌套集是实现有序树的一种聪明方法,它允许快速、非递归查询。” - 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

    【讨论】:

    • 嗨,CourseModule::whereId($id)->first()->getDescendantsAndSelf()->toHierarchy() 只返回单个节点,如果我必须对模型进行任何更改,我正在使用单个表,如顶部所示
    【解决方案2】:

    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');
    }
    

    【讨论】:

      【解决方案3】:

      您应该在子关系中使用with('children')with('parent') 在父关系中。

      让您的代码递归:

      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');
      }
      

      注意:确保您的代码具有某些或其他退出条件,否则它将进入一个永无止境的循环。

      【讨论】:

      • 有效!在第一个集合中,我有一个链式树,但在同一个子集合中重复作为父集合。我不想让孩子们再次成为根集合。有什么解决办法还是我做错了?
      • 找到解决方案$data = CourseModule::with('children')->where('parent_id', 0)
      • 我试图将结果显示为层次结构,但不能。我试过这样的东西 @foreach ($accountHeads as $accountHead) @foreach ($accountHead->children as $children) <option value="{{ $children->id }}">{{ $children->name }}</option> @endforeach @endforeach 。但它只显示那些有 parent_id = 1
      【解决方案4】:

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

      <?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;
      
          }
      
      }
      

      【讨论】:

        【解决方案5】:

        模型功能:

        public function Children()
        { 
            return $this->hasMany(self::class, 'Parent', 'Id')->with('Children');
        } 
        

        控制器功能:

        Menu::with("Children")->where(["Parent" => 0])->get(); 
        

        【讨论】:

          【解决方案6】:

          你的模型关系应该是这样的

               // parent relation
               public function parent(){
          
                  return $this->belongsTo(self::class , 'parent_id');
              }
              //child relation
               public function children()
              {
                  return $this->hasMany(self::class ,'parent_id');
              }
              public function ascendings()
              {
                  $ascendings = collect();
          
                  $user = $this;
          
                  while($user->parent) {
                      $ascendings->push($user->parent);
          
                      if ($user->parent) {
                          $user = $user->parent;
                      }
                  }
          
                  return $ascendings;
              }
          
          
          
              public function descendings()
              {
                  $descendings = collect();
                  $children = $this->children;
          
                  while ($children->count()) {
          
                      $child = $children->shift();
          
                      $descendings->push($child);
          
                      $children = $children->merge($child->children);
          
                  }
                  return $descendings;
              }
          

          【讨论】:

          • 拜托,你能用更详细的解释来扩展你的答案吗?这对理解非常有用。谢谢!
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-02-12
          • 1970-01-01
          • 2013-06-04
          • 2016-11-26
          • 2018-02-19
          • 2019-04-18
          • 2015-06-27
          相关资源
          最近更新 更多