Build a tree from a flat array in PHP
You forgot the unset()
in there bro.
function buildTree(array &$elements, $parentId = 0) {
$branch = array();
foreach ($elements as $element) {
if ($element['parent_id'] == $parentId) {
$children = buildTree($elements, $element['id']);
if ($children) {
$element['children'] = $children;
}
$branch[$element['id']] = $element;
unset($elements[$element['id']]);
}
}
return $branch;
}
The solution by ImmortalFirefly is working, however, as mrded points out, it doesn't save first parents without children. I've edited the function to fix this issue:
function buildTree(array &$elements, $parentId = 0) {
$branch = array();
foreach ($elements as &$element) {
if ($element['parent_id'] == $parentId) {
$children = buildTree($elements, $element['id']);
if ($children) {
$element['children'] = $children;
}
$branch[$element['id']] = $element;
unset($element);
}
}
return $branch;
}
This works for me:
$index=array();
$tree=array();
foreach ($ori as $key=>$var) {
$var=array_shift($ori);
if ($var['id']==0) $var['id']=$key;
if ((string)$var['parent_id']==='0') {
$tree[$key]=$var;
$index[$key]=&$tree[$key];
} else if (isset($index[$var['parent_id']])) {
if (!isset($index[$var['parent_id']]['children'])) $index[$var['parent_id']]['children']=array();
$index[$var['parent_id']]['children'][$key]=$var;
$index[$key]=&$index[$var['parent_id']]['children'][$key];
} else {
array_push($ori,$var);
}
}
unset($index);
print_r($tree);
I can see the logic, save for this in the result:
Array
(
[0] => Array
(
[id] => 0
[parent_id] => 0
)
[1] => Array
(
[id] => 1
[parent_id] => 0
)
IMHO, is parent_id = o, shouldn't [1] be a child of [0] here?
Anyway, references to the rescue:
$tree = array();
foreach($inputarray as $item){
if(!isset($tree[$item['id']])) $tree[$item['id']] = array();
$tree[$item['id']] = array_merge($tree[$item['id']],$item);
if(!isset($tree[$item['parent_id']])) $tree[$item['parent_id']] = array();
if(!isset($tree[$item['parent_id']]['children'])) $tree[$item['parent_id']]['children'] = array();
$tree[$item['parent_id']]['children'][] = &$tree[$item['id']];
}
$result = $tree[0]['children'];
unset($tree);
print_r($result);
Because you have abused 0 as both a 'magic' number as root, and an existing id, we now have recursion in the id=0 branch. Adding if($item['parent_id']!=$item['id'])
before $tree[$item['parent_id']]['children'][] = &$tree[$item['id']];
could prevent that, but it isn't pretty.
It's possible to construct the source array slightly different you can use this function(parent_id,id,title):
$q = mysql_query("SELECT id, parent_id, name FROM categories");
while ($r = mysql_fetch_row($q)) {
$names[$r[0]] = $r[2];
$children[$r[0]][] = $r[1];
}
function render_select($root=0, $level=-1) {
global $names, $children;
if ($root != 0)
echo '<option>' . strrep(' ', $level) . $names[$root] . '</option>';
foreach ($children[$root] as $child)
render_select($child, $level+1);
}
echo '<select>';
render_select();
echo '</select>';
- More efficient hierarchy system