I have an array that looks like this
array(
1 => array(
'id' => 1,
'name' => 'first',
'parent' => null
),
2 => array(
'id' => 2,
'name' => 'second',
'parent' => null
),
3 => array(
'id' => 3,
'name' => 'third',
'parent' => 1
),
4 => array(
'id' => 4,
'name' => 'fourth',
'parent' => 3
),
5 => array(
'id' => 5,
'name' => 'fifth',
'parent' => 1
),
);
But I want to move any “child” items to the “children” key under the array.
So, I want to end up with
array(
1 => array(
'id' => 1,
'name' => 'first',
'parent' => null,
'children' => array(
3 => array(
'id' => 3,
'name' => 'third',
'parent' => 1,
'children' => array(
4 => array(
'id' => 4,
'name' => 'fourth',
'parent' => 3,
'children' => array()
),
)
),
5 => array(
'id' => 5,
'name' => 'fifth',
'parent' => 1,
'children' => array()
)
)
),
2 => array(
'id' => 2,
'name' => 'second',
'parent' => null,
'children' => array()
)
);
But to be honest I have absolutely no idea where to start.
I was thinking maybe looping over each item in the array and then building the new array as I go with $new_array[$current['parent']]['children'][$current['id']] = $current;
But I run into issues as soon as I hit a nested item.
I could build a function that takes the current array, and the entire array and recursively moves up the tree to find all the parents and therefore the entire path, but I run into issues again if one of the parents has not been created yet.
The only option I could think of is to build an array map of the different levels of parents and the loop over that recursively and grab all the elements that way, but that seems somewhat inefficient?
Can anyone suggest a solution?
You had the right idea with the foreach loop. What you want to do, however, requires the ‘magic’ of references.
This will output for ‘$oldArray’
And for newArray (the ‘purified’ version)
Now, why this works:
By putting &item into the foreach loop, we work with a reference to the item, instead of a copy. That means, whatever we change about that item, we also change at the corresponding array element.
By passing &$item to $newArray[$key], or to the children array, we pass the reference along…so whatever we do to the ‘original object’ (i.e. [3]), we also do to all the references.
The unset($item) is necessary, because it erases the binding between the last instance of $item and the variable. Otherwise, we’d change the last variable as well, as soon as we change the $item variable once more. Not exactly necessary in this script, but still a good practice to remember.