PHP Building Recursive Array from List
Solution 1
<?php
$pages = array();
$pages[1] = array('id' => 1, 'parent' => 0, 'name' => 'Hello World');
$pages[2] = array('id' => 1, 'parent' => 1, 'name' => 'Child of Hello World');
$pages[3] = array('id' => 1, 'parent' => 0, 'name' => 'Brother of Hello World');
$pages[4] = array('id' => 4, 'parent' => 2, 'name' => 'Grand-child of Hello World');
$pages[6] = array('id' => 6, 'parent' => 4, 'name' => 'Great-grand-child of Hello World');
$children = array();
foreach($pages as $key => $page){
$parent = (int)$page['parent'];
if(!isset($children[$parent]))
$children[$parent] = array();
$children[$parent][$key] = array('id' => $page['id'], 'name' => $page['name']);
}
$new_pages = recursive_append_children($children[0], $children);
function recursive_append_children($arr, $children){
foreach($arr as $key => $page)
if(isset($children[$key]))
$arr[$key]['children'] = recursive_append_children($children[$key], $children);
return $arr;
}
print_r($new_pages);
?>
Outputs:
Array
(
[1] => Array
(
[id] => 1
[name] => Hello World
[children] => Array
(
[2] => Array
(
[id] => 1
[name] => Child of Hello World
[children] => Array
(
[4] => Array
(
[id] => 4
[name] => Grand-child of Hello World
[children] => Array
(
[6] => Array
(
[id] => 6
[name] => Great-grand-child of Hello World
)
)
)
)
)
)
)
[3] => Array
(
[id] => 1
[name] => Brother of Hello World
)
)
Solution 2
Here is a quick recursive function that builds a tree. Note that it's not great (one reason is because it doesn't get rid of items that have been already added to the tree, so each time you recurse it goes thru the entire list) - but it should work enough to get you started.
function buildTree($itemList, $parentId) {
// return an array of items with parent = $parentId
$result = array();
foreach ($itemList as $item) {
if ($item['parent'] == $parentId) {
$newItem = $item;
$newItem['children'] = buildTree($itemList, $newItem['id']);
$result[] = $newItem;
}
}
if (count($result) > 0) return $result;
return null;
}
$myTree = buildTree($myArray, 0);
j6mes
Some of my sites: https://jthorne.co.uk - Personal blog http://snip.so - Free screenshot share tool
Updated on September 05, 2022Comments
-
j6mes over 1 year
I am returning a list of pages and their parent pages from a MySQL database and putting all results into an array as follows where every result is an array which includes the parent, name and id of the forum (the key of array pages is also the same as page id).
For the sake of the model and the applicaiton, there are some other parameters.
- "root pages" have a parent of 0
- there are no orphaned pages
so, the MySQL query will return this dataset.
pages=> [1] => array(id=>1, parent=>0, name=>Hello World) [2] => array(id=>1, parent=>1, name=>Child of Hello World) [3] => array(id=>1, parent=>0, name=>Brother of Hello World) [4] => array(id=>4, parent=>2, name=Grand-child of Hello World) [6] => array(id=>6, parent=>4, name=Great-grand-child of Hello World)
i would then like to transform the array into something that looks like this
pages=> [1] => id=>1, name=>Hello World children=> [2] => id=>1 name=>Child of Hello World children=> [4] => id=>4 name=> Grand-child of Hello World) children=> [6] => id=>6 name=> Great-grand-child of Hello World children= null [3] => array(id=>1, name=>Brother of Hello World children=>null
So basically, i want to turn a linear array into a nested multidimensional array so that i can print my sitemap.
it needs to be a recursive solution. there are over 700 pages and up to 5 or 6 levels.
i only want to do 1 mysql query. not 700 so please dont give me a mysql based solution.
-
Paul over 12 yearsThis is O(N) time complexity, since both loops can be shown to look at each element in the array exactly one time.
-
j6mes over 12 yearsthank you for your response. just made a few minor tweaks to adjust it to the entire data array but great answer thanks. so $children[$parent][$key] = array('id' => $page['id'], 'name' => $page['name']); is now $children[$parent][$key] = $pages[$key];
-
j6mes over 12 yearsthanks for helping. i didnt use this but gave me a good idea of how i would do it next time.
-
Paul over 12 years@Partydroid You're welcome. Only difference is that will keep the
parent
values in your resulting array, which it looks like you wanted to get rid of. You could always justunset($children[$parent][$key]['parent']);
though too. -
Nic about 8 years@Paulpro I know this is very old but I think that in the first
foreach
instead of$children[$parent][$key]
it should be$children[$parent][$page['id']]