3

I'm currently programmatically generating a menu and menu links inside it. This is working but I'm having trouble setting the parents for the links. Here is my current code

    $langcode = 'es';
    if (empty($menu_id)) {return ['#markup' => 'menu not specified'];}
    $menu = \Drupal::entityTypeManager()->getStorage('menu')
        ->create([
            'langcode' => $langcode,
            'status' => TRUE,
            'label' => $menu_id,
            'id' => $menu_id,
            'description' => 'this menu was created programmatically',
        ])->save();

    $items = [
        '1' => 'item 1',
        '2' => 'item 2',
        '3' => 'item 3',
    ];
    $parent = NULL;
    foreach ($items as $id => $title) {
        if ($id == '2') {$parent = '1';} else { $parent == NULL;}
        $menu_link = MenuLinkContent::create([
            'title' => $title,
            'link' => ['uri' => 'internal:/node/' . $nid],
            'menu_name' => $menu_id,
            'expanded' => true,
            'langcode' => $langcode,
            'status' => TRUE,
            'parent' => $parent,
        ]);

        $menu_link->save();
        var_dump($menu_link->getParentId());
    }

This line

var_dump($menu_link->getParentId());

is actually displaying the correct parent. But when visiting the menu in the admin page the parent is not set and is at the top level of the menu. Is there a specific issue with my code? How would you set the parent of a programmatically generated menu link?

2

Turns out when setting the parent you don't use the id of the menu_link_content you use the 'menu_link_content:' followed by the uuid of the link. Here's an example of a properly formatted parent field.

'menu_link_content:0025c274-4db3-4745-b51e-714c998b5a50'

I fixed the code like so

    foreach ($items as $id => $title) {
        if ($id == '2') {
            $parent = 'menu_link_content:' . $previous_menu_link->uuid();
        } else {
            $parent == NULL;
        }

        $menu_link = MenuLinkContent::create([
            'title' => $title,
            'link' => ['uri' => 'internal:/node/' . $nid],
            'menu_name' => $menu_id,
            'expanded' => true,
            'langcode' => $langcode,
            'status' => TRUE,
            'parent' => $parent,
        ]);

        $menu_link->save();
        $previous_menu_link = $menu_link;
    }
  • 1
    Thanks for posting this! I was building some ridiculously complex setup to create a hierarchical menu... then realized I could do it as you're doing, with an array of menu items, just by setting a value like 'top_level' => TRUE and keying on that to flag when there's a top level item to store it's UUID and use it for the children in a loop. – geerlingguy Feb 13 at 1:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.