I have a sample 2d $tasks array which describes a nested structure :
Array
(
[14] => Array
(
[Id] => 14
[parentId] => null
[Name] => T1
)
[40] => Array
(
[Id] => 40
[parentId] => null
[Name] => T5
)
[41] => Array
(
[Id] => 41
[parentId] => null
[Name] => T4
)
[22] => Array
(
[Id] => 22
[parentId] => 14
[Name] => T2
)
[43] => Array
(
[Id] => 43
[parentId] => 22
[Name] => T2 child
)
[42] => Array
(
[Id] => 42
[parentId] => 14
[Name] => T3
)
)
Using the code below I'm transforming this to a proper tree structure :
$sortedArray = array();
// get first level
foreach($tasks as $k => $v){
if($v['parentId'] == 'null'){
$sortedArray[$k] = $v;
unset($tasks[$k]);
}
}
// sort parents
asort($sortedArray);
function getChildren(array & $a1, array & $a2){
foreach($a1 as $k => $v){
findChildren($v, $a2, $k);
}
}
function findChildren($rec1, array & $a2, $key){
foreach($a2 as $k => $v){
if($rec1['parentId'] == $v['Id']){
$a2[$k]['children'][$rec1['Id']] = $rec1;
unset($tasks[$key]);
} else {
if (isset($v['children'])){
findChildren($rec1, $a2[$k]['children'], $key);
}
}
}
}
findChildren($tasks, $sortedArray);
And tho output $sortedArray after running this code looks as follows :
Array
(
[14] => Array
(
[Id] => 14
[parentId] => null
[Name] => T1
[children] => Array
(
[22] => Array
(
[Id] => 22
[parentId] => 14
[Name] => T2
[children] => Array
(
[43] => Array
(
[Id] => 43
[parentId] => 22
[Name] => T2 child
)
)
)
[42] => Array
(
[Id] => 42
[parentId] => 14
[Name] => T3
)
)
)
[40] => Array
(
[Id] => 40
[parentId] => null
[Name] => T5
)
[41] => Array
(
[Id] => 41
[parentId] => null
[Name] => T4
)
)
The problem is, that after calling json_encode on this output array in it's current state I'm getting :
{"14":{"Id":"14","parentId":"null"...
so all nested arrays are inserted with their indexes. I know I can fix the first level using array_values. But is there any simple way of doing this for all levels ? Without it I end up with 'children' being not an array but object which is not satisfying for me.
The code isn't present in your post, but $tasks was created as an associative array. In your example you also iterate through $tasks as you would an associative array:
foreach($tasks as $k => $v){
...
}
You need to add children to $tasks as you would with a numeric array; the difference is this:
//associative array
$test = array();
$test["43"] = "hello";
$test["40"] = "hello1";
$test["23"] = "hello2";
print_r($test);
//numeric array
$testb = array();
$testb[] = "hello";
$testb[] = "hello1";
$testb[] = "hello2";
print_r($testb);
Live example: http://codepad.org/tsOhX88h
With the numeric array, the top level index (e.g., 14) you've cited as the problem {"14":{"Id":"14","parentId":"null"... is no longer present.
As a simple final step, use this code to push the items from the associative array on to a new numeric array:
$finalArray = array();
foreach ($sortedArray as $key=>$val ){
$finalArray[] = $sortedArray[$key];
}
print_r($finalArray);
Live example: http://codepad.org/uSGSr1DC
Or you could do it in one shot with array_values:
$finalArray = array();
$finalArray = array_values($sortedArray);
print_r($finalArray);
Live example: http://codepad.org/D7uBSRr8
You did not include your json_encode call, if you happened to do it like this...
json_encode(array_values($sortedArray), JSON_FORCE_OBJECT);
then the force will put the numeric indexes in anyway. Not sure if this will help you but it might help someone else who's seeing the same problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With