phprecursionhierarchy

Flatten multidimensional array 1 level php


I am building a hierarchy for categories.

I am using a recursive function to build child parent relationship. This builds a nested set of arrays for each child.

I want to flatten this nested array to 1 level. There are lots of ways to completely flatten a multidimensional array, but I want to rebuild the array for JSON, maintaining each category id and name together in the array.

I get this output:

array(2) { 
    [0] => array(2) {
        ["id"] => int(223)    
        ["name"] => string(12) "child of top" 
        ["parent"] => int(222)
    }  
    [1] => array(1) {    
        [0]=> array(2) {      
            [id] => int(224)      
            ["name"] => string(21) "child of child of top"    
            ["parent"] => int(222)
        }
    }
}

But I would like to have:

array(2) { 
    [0] => array(2) {
        ["id"] => int(223)    
        ["name"] => string(12) "child of top" 
        ["parent"] => int(222)
    }  
    [1] => array(2) {      
        ["id"] => int(224)      
        ["name"] => string(21) "child of child of top"
        ["parent"] => int(223)
    }
}

Which I can then build into the correct child parent relation.

It is the first time I am building this kind of structure so I am a little overwhelmed with trying to format things correctly.

Any recommendations to move forward with this? Thanks.

edit added function

  function display_children($cat_id, $level) { 

            $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) or die ("Error " . mysqli_error($conn));
            $stmt = $mysqli->prepare("SELECT id, content, parent_id 
                                        FROM table
                                            WHERE parent_id = ?
                                        ");
            $stmt->bind_param("i", $cat_id);
            $stmt->execute();
            $result = $stmt->get_result();
            $stmt->close();

            while( $row = $result->fetch_assoc() ) {
                $data_array[] = $row; 

                $data_array[] = display_children($row['id'], $level+1);
            }
            return $data_array;
        }

more info The first suggested answer isn't quite there as the children from all levels are not being returned up the parent levels.

parent: int(229)\n
       recursion[0]: array(3) {\n  [\"id\"]=>\n  int(232)\n  [\"content\"]=>\n  string(7) \"level 4\"\n  [\"parent_id\"]=>\n  int(231)\n}\n
            array(2) {\n    [0]=>\n  array(3) {\n    [\"id\"]=>\n    int(231)\n    [\"content\"]=>\n    string(7) \"level 3\"\n    [\"parent_id\"]=>\n    int(229)\n  }\n  
                            [1]=>\n  array(3) {\n    [\"id\"]=>\n    int(232)\n    [\"content\"]=>\n    string(7) \"level 4\"\n    [\"parent_id\"]=>\n    int(231)\n  }\n}\n 
parent: int(228)\n
        recursion[0]: array(3) {\n  [\"id\"]=>\n  int(231)\n  [\"content\"]=>\n  string(7) \"level 3\"\n  [\"parent_id\"]=>\n  int(229)\n}\n
            array(2) {\n    [0]=>\n  array(3) {\n    [\"id\"]=>\n    int(229)\n    [\"content\"]=>\n    string(7) \"level 2\"\n    [\"parent_id\"]=>\n    int(228)\n  }\n  
                            [1]=>\n  array(3) {\n    [\"id\"]=>\n    int(231)\n    [\"content\"]=>\n    string(7) \"level 3\"\n    [\"parent_id\"]=>\n    int(229)\n  }\n}\n 
parent: int(227)\n
        recursion[0]: array(3) {\n  [\"id\"]=>\n  int(229)\n  [\"content\"]=>\n  string(7) \"level 2\"\n  [\"parent_id\"]=>\n  int(228)\n}\n
            array(2) {\n    [0]=>\n  array(3) {\n    [\"id\"]=>\n    int(228)\n    [\"content\"]=>\n    string(7) \"level 1\"\n    [\"parent_id\"]=>\n    int(227)\n  }\n  
                           [1]=>\n  array(3) {\n    [\"id\"]=>\n    int(229)\n    [\"content\"]=>\n    string(7) \"level 2\"\n    [\"parent_id\"]=>\n    int(228)\n  }\n}\n

Final output for JSON:

   [{\"id\":228,\"content\":\"level 1\",\"parent_id\":227},{\"id\":229,\"content\":\"level 2\",\"parent_id\":228}]"

using this check in the loop:

  if( isset( $recursion[0] ) ){
      $data_array[] = $recursion[0];
         echo " parent: ";
         var_dump($cat_id)
         echo "recursion[0]: " 
         var_dump( $recursion[0], $data_array);
 }

I think I have the answer:

if( isset( $recursion[1] ) ){
  $data_array = array_merge($recursion,$data_array);
} elseif ( isset( $recursion[0] ) ){
  $data_array[] = $recursion[0];
}

If there is more than 1 value in the recursion return then there are children of children being returned up the recursion. More than just the child of the current parent. It is required to return the whole recursion array. Then merge the array with the current parent. I haven't tested this thouroughly yet, but seems to be going well.


Solution

  • if the structure is as the example this should work:

    function display_children($cat_id, $level) { 
    
            $mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) or die ("Error " . mysqli_error($conn));
            $stmt = $mysqli->prepare("SELECT id, content, parent_id 
                                        FROM table
                                            WHERE parent_id = ?
                                        ");
            $stmt->bind_param("i", $cat_id);
            $stmt->execute();
            $result = $stmt->get_result();
            $stmt->close();
    
            while( $row = $result->fetch_assoc() ) {
                $data_array[] = $row; 
                $recursion = display_children($row['id'], $level+1);
                if(isset($recursion['id']))
                   $data_array[] = $recursion;
                elseif(isset($recursion[0]))
                   $data_array[] = $recursion[0];
                else
                   //manage error
            }
            return $data_array;
        }