Search code examples
phparraysjsonmultidimensional-arrayflatten

Flatten an array with parent-child relationships so that all children are on the parent level


Good morning, given the below data structure (in JSON for ease of reading)

[
{
    "parent": "root",
    "active": "1",
    "label": "Index",
    "route": "/",
    "children": [
        {
            "parent": "/",
            "active": "1",
            "label": "Products",
            "route": "/products",
            "children": [
                {
                    "parent": "/products",
                    "active": "0",
                    "label": "Test",
                    "route": "/test"
                }
            ]
        }
    ]
    },
    {
        "parent": "root",
        "active": "1",
        "label": "404",
        "route": "/404"
    },
    {
        "parent": "root",
        "active": "1",
        "label": "Login",
        "route": "/login"
    }
]

I am having major trouble returning from a function the following structure:

[
{
    "parent": "root",
    "active": "1",
    "label": "Index",
    "route": "/"
},
{
    "parent": "/products",
    "active": "0",
    "label": "Test",
    "route": "/test"
},
{
    "parent": "/",
    "active": "1",
    "label": "Products",
    "route": "/products"
},
{
    "parent": "root",
    "active": "1",
    "label": "404",
    "route": "/404"
},
{
    "parent": "root",
    "active": "1",
    "label": "Login",
    "route": "/login"
}
]

Essentially I want to recurse through all the children and populate a new array with every parent and child in the nested arrays, I have tried array_merge, RecursiveIteratorIterator, iterator_to_array, array_map, but it always comes unstuck on the recursion. I managed to do it when the children were only one level deep but two or more simply breaks down.


Solution

  • Not very hard:

    function flatten(array $array) {
        $branch = [];
    
        foreach ($array as $item) {
            $children = [];
            if (isset($item['children']) && is_array($item['children'])) {
                $children = flatten($item['children']);
                unset($item['children']);
            }
            $branch = array_merge($branch, [$item], $children);
        }
    
        return $branch;
    }