Eloquent Parent-Child relationship on same model

前端 未结 6 1468
醉酒成梦
醉酒成梦 2020-12-03 07:42

I have a model CourseModule, and each of the items are related to the same model.

Database Structure:

Relation in Model:



        
相关标签:
6条回答
  • 2020-12-03 07:55

    here is the answer that can help you

    I think you you have to do it recursively to retrieve whole tree:

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

    Recursive function

    This may help you according to your requirement,

    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');
    }
    
    0 讨论(0)
  • 2020-12-03 08:08

    You should use with('children') in the children relation and with('parent') in the parent relations.

    For your code to be recursive:

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

    Note: Make sure your code has some or the other exit conditions otherwise it will end up in a never ending loop.

    0 讨论(0)
  • 2020-12-03 08:08

    Model Function:

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

    Controller Function:

    Menu::with("Children")->where(["Parent" => 0])->get(); 
    
    0 讨论(0)
  • 2020-12-03 08:09

    You would have to recursively get the children if you have an unknown depth like that.

    Another option is to use the nested sets model instead of the adjacency list model. You can use something like baum/baum package for Laravel for nested sets.

    "A nested set is a smart way to implement an ordered tree that allows for fast, non-recursive queries." - https://github.com/etrepat/baum

    With this package you have methods like getDescendants to get all children and nested children and toHierarchy to get a complete tree hierarchy.

    Wikipedia - Nested Set Model

    Baum - Nested Set pattern for Laravel's Eloquent ORM

    Managing Hierarchical Data in MySQL

    0 讨论(0)
  • 2020-12-03 08:16

    your model relationship should like this

         // 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;
        }
    
    0 讨论(0)
  • 2020-12-03 08:17

    You can always create your own recursive function, in my case I do as the code as follow.

    <?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;
    
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题