Tommy001
9 months ago

Why do I only get one child per parent?

Posted 9 months ago by Tommy001

I am trying to build a genealogy tree from a single persons table containing id, name, mother_id and father_id. The mother_id and father_id points to the persons parents and if these are both null, it means that this person is at the top level in the tree.

I found an answer to a similar question at https://laravel.io/forum/06-27-2014-unlimited-depth-nested-eloquent-collection, and I have adapted the code to almost work as I want. I get the top level persons as expected, but only 1 child for every person that has children.

I have this code so far in my controller:

    public function parenttree()
    {
      $family_id = auth()->user()->family_id;
      $tree = array();
      //GET TOP LEVEL ITEMS
      $top_level = Person::where('family_id', $family_id)
      ->where('mother_id', null)
      ->where('father_id', null)
      ->get();

      foreach($top_level as $top){
        $branch = array();
        $branch['id'] = $top->id;
        $branch['name'] = $top->name;
        $children = Person::where('family_id', $family_id)
        ->where('mother_id', $top->id)
        ->orWhere('father_id', $top->id)
        ->get();
        //CHECK FOR CHILDREN
        if($children->count() > 0) {
            //THERE ARE CHILDREN PASS THEM TO A RECURSIVE FUNCTION TO GET LIST
            $branch['children'] = $this->getChildren($children);
        } else {
            //THERE ARE NO CHILDREN SET TO EMPTY ARRAY
            $branch['children'] = array();
        }
        $tree[] = $branch;
      }

  dd($tree);

        return view('/family/familytree', ['persons'=>$persons]);
    }

    function getChildren($children) {
      $family_id = auth()->user()->family_id;
      foreach($children as $child){
        $child_branch = array();
        $child_branch['id'] = $child->id;
        $child_branch['name'] = $child->name;
        $children = Person::where('family_id', $family_id)
        ->where('mother_id', $child->id)
        ->orWhere('father_id', $child->id)
        ->get();
        //CHECK FOR CHILDREN
        if($children->count() > 0) {
          //THERE ARE CHILDREN PASS THEM TO THIS FUNCTION (RECURSION) TO GET LIST
          $child_branch['children'] = $this->getChildren($children);
      }  else {
          //THERE ARE NO CHILDREN SET TO EMPTY ARRAY
          $child_branch['children'] = array();
        }

        return $child_branch;
      }
    }

And this is how the dd($tree) looks like, There should be more than one child on the last level.

array:5 [▼
  0 => array:3 [▶]
  1 => array:3 [▶]
  2 => array:3 [▼
    "id" => 22
    "name" => "Anders Lindgren"
    "children" => array:3 [▼
      "id" => 12
      "name" => "Maria Lindgren"
      "children" => array:3 [▼
        "id" => 14
        "name" => "David Lindgren"
        "children" => []
      ]
    ]
  ]
  3 => array:3 [▶]
  4 => array:3 [▶]
]
´´´

Please sign in or create an account to participate in this conversation.