rod25 Posted March 13, 2017 Share Posted March 13, 2017 Hello, Im trying to create nested blocks of HTML code from a Multidimensional Array in PHP using a recursive function. However I can not seem to print the tags in a nested order. Here is the original array: $array_1 = array ( array ( 'id' => '1', 'tag' => 'div1', 'parent' => '0' ), array ( 'id' => '2', 'tag' => 'div2', 'parent' => '1' ), array ( 'id' => '3', 'tag' => 'div3', 'parent' => '2' ), array ( 'id' => '4', 'tag' => 'div4', 'parent' => '2' ), array ( 'id' => '5', 'tag' => 'div5', 'parent' => '0' ), array ( 'id' => '6', 'tag' => 'div6', 'parent' => '5' ), array ( 'id' => '7', 'tag' => 'div7', 'parent' => '0' ) ); The first thing I do is to use a function to turn this array into a multidimensional array by building a tree structure using the parent element of each record as reference: function buildTree(array $elements, $parentId = 0) { $branch = array(); foreach ($elements as $element) { if ($element['parent'] == $parentId) { $children = buildTree($elements, $element['id']); if ($children) { $element['children'] = $children; } $branch[] = $element; } } return $branch; } $tree_1 = buildTree($array_1); Once this is done the multidimensional array should look like this: Array ( [0] => Array ( [id] => 1 [name] => div1 [parent] => 0 [children] => Array ( [0] => Array ( [id] => 2 [name] => div2 [parent] => 1 [children] => Array ( [0] => Array ( [id] => 3 [name] => div3 [parent] => 2 ) [1] => Array ( [id] => 4 [name] => div4 [parent] => 2 ) ) ) ) ) [1] => Array ( [id] => 5 [name] => div5 [parent] => 0 [children] => Array ( [0] => Array ( [id] => 6 [name] => div6 [parent] => 5 ) ) ) [2] => Array ( [id] => 7 [name] => div7 [parent] => 0 ) ) The next thing to do is to output the html elements in a nested order. In this example Im using symbolic tag names such as div1, div2, etc; but in reality they could be any html tags like divs, h1, ul,li, form, etc; with their opening and closing tags. To accomplish this I use the following recursive function, however my problem is that it does not show the html elements in a nested order as they should be. function recursive($array, $level = 0) { foreach($array as $key => $value) { if (!is_array($value) && $key == "tag") { echo str_repeat(" ", $level), "[".$value."]", ''; } //If $value is an array. if(is_array($value)) { //We need to loop through it. recursive($value, $level + 1); } else { //It is not an array, so print it out. if ($key == "tag") { echo "[/".$value."]", '<br>'; } } } } $tree_2 = recursive($tree_1); echo $tree_2; This is how it currently outputs the html tags from the array: [div1][/div1] [div2][/div2] [div3][/div3] [div4][/div4] [div5][/div5] [div6][/div6] [div7][/div7] And this is how the html tags should be output in reality based on the multidimensional array's nested order (please note how some div tags contain other div tags before their closing element): [div1] [div2] [div3][/div3] [div4][/div4] [/div2] [/div1] [div5] [div6][/div6] [/div5] [div7][/div7] How can I get the html tags printed in the right nested order like in the last example? What am I missing? Thanks so much! Quote Link to comment Share on other sites More sharing options...
gen25 Posted March 13, 2017 Share Posted March 13, 2017 i think this will do it function recursive($array, $level = 0) { foreach($array as $key => $value) { if (is_array($value)) { echo str_repeat(" ", $level), "[".$value['tag']."]<br>", ''; if (@$value['children']) { recursive($value['children'], $level + 1); } echo str_repeat(" ", $level), "[/".$value['tag']."]<br>", ''; } } } Quote Link to comment Share on other sites More sharing options...
Psycho Posted March 13, 2017 Share Posted March 13, 2017 After creating your multi-dimensional array, you can use this to output the content. I put in logic to add spacing at each level to make it easy to "see" the structure of the HTML. <?php function createOutput($array, $level=0) { //Create variable to hold output $output = ''; //Create number of tabs for spacing the level $tabs = str_repeat (" ", $level); //Iterate through each element in the current level foreach($array as $record) { //Open div for the current record $output .= "{$tabs}<div id=\"{$record['id']}\">\n"; //Show current record name $output .= "{$tabs}\t{$record['tag']}\n"; //Check if there are children if(isset($record['children']) && count($record['children'])) { //Include children output $output .= createOutput($record['children'], $level+1); } //Close div for current record $output .= "{$tabs}</div>\n"; } //Return the results return $output; } ?> Output <div id="1"> div1 <div id="2"> div2 <div id="3"> div3 </div> <div id="4"> div4 </div> </div> </div> <div id="5"> div5 <div id="6"> div6 </div> </div> <div id="7"> div7 </div> Quote Link to comment Share on other sites More sharing options...
thinsoldier Posted March 17, 2017 Share Posted March 17, 2017 (edited) Oh yeah. I've reinvented this wheel a few times. Inevitably you will find yourself in a situation where you want to manipulate attributes on the tag or change the tag from a div to an li or span or something else. My preferred approach is to use an actual html dom building tool like querypath so that you can construct your html using methods that feel just like jQuery and cache the result. https://github.com/technosophos/querypath Edited March 17, 2017 by thinsoldier Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.