phparraysrecursionmultidimensional-arrayhierarchical-data

Convert an array of objects into a multidimensional array with parent-child relationships


I have an array in php with Objects containing an id and a parent_id. All Objects without a parent_id should be the root Objects in a new array.

All Objects that do have a parent_id should be pushed in the correct Object's children array:

So this is my original array:

array
  0 => 
    object(Node)[528]
      protected 'id' => int 1
      protected 'parent_id' => null
  1 =>
   object(Node)[529]
      protected 'id' => int 2
      protected 'parent_id' => null
  2 => 
   object(Node)[530]
      protected 'id' => int 3
      protected 'parent_id' => 1
  3 =>  
   object(Node)[531]
      protected 'id' => int 4
      protected 'parent_id' => 1
  4 =>  
  object(Node)[532]
      protected 'id' => int 5
      protected 'parent_id' => 4
  5 =>  
  object(Node)[533]
      protected 'id' => int 6
      protected 'parent_id' => 4

this is what the new array should look like:

$nodes = array(
  array(
   'id' => 1,
   'parent_id' => null,
   'children' => array(
    array(
     'id' => 3,
     'parent_id' => 1,
     'children' => null
    ),
    array(
     'id' => 4,
     'parent_id' => 1,
     'children' => array(
      array(
       'id' => 5,
       'parent_id' => 4
      ),
      array(
       'id' => 6,
       'parent_id' => 5
      ), 
     )
    ),
   ),
  ),
  array(
   'id' => 2,
   'parent_id' => null,
   'children' => null
  ),
 );

Any Idea how I could do this?


Solution

  • Try something like this:

    // collects all nodes that belong to a certain parent id
    function findChildren($nodeList, $parentId = null) {
        $nodes = array();
    
        foreach ($nodeList as $node) {
            if ($node['parent_id'] == $parentId) {
                $node['children'] = findChildren($nodeList, $node['id']);
                $nodes[] = $node;
            }
        }
    
        return $nodes;
    }
    

    Use it like this:

    $nestedNodes = findChildren($nodeList);
    

    This code recursively searches for the given parent_id in the original $nodeList. If a matching node is found, it searches for the children of this node, and so on. If no children for the given parent_id are found, an empty array is retuned.

    You could reduce the memory usage of this approach by using references for $nodeList.