1

Been trying to solve this with help of Laravel collections or array helpers in most efficient way. Can anyone help with this?

$menu = [
    ["id"=>1],
    ["id"=>2],
    ["id"=>3,"children"=>[
        ["id"=>4]
    ]],
    ["id"=>5,"children"=>[
        ["id"=>6],
        ["id"=>7,"children"=>[
            ["id"=>8],
            ["id"=>9]
        ]]
    ]],
    ["id"=>10]
];

$pages = [
    ['id'=>1,'label'=>'About Us','url_path'=>'/about-us'],
    ['id'=>2,'label'=>'Meet the Team','url_path'=>'/meet-the-team'],
    ['id'=>3,'label'=>'Services','url_path'=>'/services'],
    ['id'=>4,'label'=>'Contact Us','url_path'=>'/contact-us'],
    ['id'=>5,'label'=>'Company Mission','url_path'=>'/company-mission'],
    ['id'=>6,'label'=>'History','url_path'=>'/history'],
    ...
    ...
];

The ID key from nested array $menu needs to search through $pages array based on same ID and then merge this whole row back to $menu.

My Function:

$menu = collect($menu)->map(function($item) use($pages){
    $page_item = collect($pages)->firstWhere('id',$item['id']);
    if(array_has($item,'children')){
        $page_item['children'] = ...
    }
    return $page_item;
})->toArray();

How do I add the array data from $pages to "children" with recursive iteration? And is there better way to make this function more efficient? I want to make use of Laravel collections or array helpers to solve this instead of using foreach loop, etc.

Below is the expected result:

$menu = [
    ["id"=>1,"label"=>"About Us","url_path"=>"/about-us"],
    ["id"=>2,"label"=>"Meet the Team","url_path"=>"/meet-the-team"],
    ["id"=>3,"label"=>"Services","url_path"=>"/services","children"=>[
        ["id"=>4,"label"=>"Contact Us","url_path"=>"/contact-us"]
    ]],
    ["id"=>5,"label"=>"Company Mission","url_path"=>"/company-mission","children"=>[
        ["id"=>6,"label"=>"History","url_path"=>"/history"],
        ["id"=>7, ...
    ...
];

Can anyone show me? Thanks!

0

1 Answer 1

2

You can achieve this by using a recursive function as,

function map_pages_to_menu(array $pages, array $menu) {
    return collect($menu)->map(function ($menu_item) use ($pages){

        // find the page item that matches menu id
        $page_item = collect($pages)->firstWhere('id',$menu_item['id']);

        // if there is a match create the menu item from the page item
        $menu_item = $page_item ? array_merge($menu_item, $page_item) : [];

        // if there are children inside menu item, recursively find matching page items.
        if(array_has($menu_item,'children')){
            $menu_item['children'] = map_pages_to_menu($pages, $menu_item['children']);
        }

        return $menu_item;
    })
    // to remove empty items & reset index
    ->filter()->values()
    ->toArray();
}

$menu = '[
    {"id":1},
    {"id":2},
    {"id":3,"children":[
        {"id":4}
    ]},
    {"id":5,"children":[
        {"id":6},
        {"id":7,"children":[
            {"id":8},
            {"id":9}
        ]}
    ]},
    {"id":10}
]';

$menu = json_decode($menu, true);

$pages = [
    ['id'=>1,'label'=>'About Us','url_path'=>'/about-us'],
    ['id'=>2,'label'=>'Meet the Team','url_path'=>'/meet-the-team'],
    ['id'=>3,'label'=>'Services','url_path'=>'/services'],
    ['id'=>4,'label'=>'Contact Us','url_path'=>'/contact-us'],
    ['id'=>5,'label'=>'Company Mission','url_path'=>'/company-mission'],
    ['id'=>6,'label'=>'History','url_path'=>'/history']
];

$menu = map_pages_to_menu($pages, $menu);

echo json_encode($menu);

Snippet : https://implode.io/yTmrDO

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for answering!
I think there must be error I'd like to point out. Under if... loop statement for 'children', map_pages_to_menu($pages, $menu_item['children'] instead of map_pages_to_menu($menu_item['children'],$pages) to avoid empty array in loops as the IDs from $menu are belonged to $pages.
Thanks. Updated the answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.