The problem is that each child element is bound to each parent element, which is why everything is duplicated
<?php
$json = '[
{"id":3633,"name":"Mobile phones and accessories","left":1,"right":18,"level":1,"elements":0},
{"id":3638,"name":"Mobile phones","left":2,"right":3,"level":2,"elements":174},
{"id":21396,"name":"Tablets","left":19,"right":24,"level":1,"elements":0},
{"id":21450,"name":"Some Tablets","left":20,"right":21,"level":2,"elements":8}
]';
$data = json_decode($json, true);
function buildTree($data, $level = 1) {
$tree = array();
foreach ($data as $item) {
if ($item['level'] == $level) {
$node = array(
'item' => $item,
'children' => buildTree($data, $level + 1),
);
$tree[] = $node;
}
}
return $tree;
}
$tree = buildTree($data);
print_r($tree);
?>
It turns out that this is the output of the elements
Array
(
[0] => Array
(
[item] => Array
(
[id] => 3633
[name] => Mobile phones and accessories
[left] => 1
[right] => 18
[level] => 1
[elements] => 0
)
[children] => Array
(
[0] => Array
(
[item] => Array
(
[id] => 3638
[name] => Mobile phones
[left] => 2
[right] => 3
[level] => 2
[elements] => 174
)
[children] => Array
(
)
)
[1] => Array
(
[item] => Array
(
[id] => 21450
[name] => Some Tablets
[left] => 20
[right] => 21
[level] => 2
[elements] => 8
)
[children] => Array
(
)
)
)
)
[1] => Array
(
[item] => Array
(
[id] => 21396
[name] => Tablets
[left] => 19
[right] => 24
[level] => 1
[elements] => 0
)
[children] => Array
(
[0] => Array
(
[item] => Array
(
[id] => 3638
[name] => Mobile phones
[left] => 2
[right] => 3
[level] => 2
[elements] => 174
)
[children] => Array
(
)
)
[1] => Array
(
[item] => Array
(
[id] => 21450
[name] => Some Tablets
[left] => 20
[right] => 21
[level] => 2
[elements] => 8
)
[children] => Array
(
)
)
)
)
)
Now I have every element with level = 2 tied to every element with level = 1
But there should be no duplication
What can be changed so that all elements are unique and belong to only one parent
2
Answers
If you want it by parsed by order, all level 1 are siblings, and otherwise each item is a child of the previous then here’s a javascript pseudo-code.
I see two problems in your code:
$level
is greater than$item['level']
For the first point, a simple
if
suffices to solve the problem.For the second point I suggest to use an iterator in place of an array to keep the pointer positions trough the different calls.
demo
This code is written for PHP 8.x, feel free to remove the types in the function signature to make it work with older versions.