12

I need to add some links to existing menu (or to new) programmatically in Drupal 8.

22

In order to create a menu item automatically this can be placed in a hook_update_N on the file mymodule.install and will run when the database is updated (/update.php):

use Drupal\menu_link_content\Entity\MenuLinkContent;
$items = array(
  '1' => 'Menuitem 1',
  '2' => 'Menuitem 2',
  '3' => 'Menuitem 3'
);

foreach($items as $nid => $title) {
  $menu_link = MenuLinkContent::create([
    'title' => $title,
    'link' => ['uri' => 'internal:/node/' . $nid],
    'menu_name' => 'main',
    'expanded' => TRUE,
  ]);
  $menu_link->save();
}

You can also create an entire Menu programmatically:

\Drupal::entityTypeManager()
  ->getStorage('menu')
  ->create([
    'id' => 'menu_test',
    'label' => 'Test menu',
    'description' => 'Description text',
  ])
  ->save();
  • 1
    entity_create is deprecated. Use \Drupal::entityTypeManager()->get storage('menu')-create([]); – Eyal Apr 6 '16 at 11:47
  • 1
    I think that the correct solution should use the menu yamls – Eyal Apr 6 '16 at 11:48
  • 3
    in which hook is this used properly? – Paul Sep 19 '16 at 12:14
  • 11
    Would it be ok to expand the answer? It doesn't state where this code can be placed to generate the menu items. I think people like me will struggle to take this and implement it effectively. – cwiggo Jan 25 '17 at 12:30
  • 6
    How would you add a menu link as a child to a parent link? – Matt Apr 14 '17 at 17:56
7

If you would like to create module-defined menu links, add something like this example to your custom_module.links.menu.yml file:

custom_module.admin_item_1:
  title: 'New Admin Item 1'
  parent: system.admin
  description: 'Description of link goes here.'
  route_name: view.some_view_id.page_1

parent (optional) is the id column of the parent in the menu_tree table, and route_name is Drupal's internal route ID for where you'd like the menu item to link to. It's in the menu_tree table as route_name.

See Providing module-defined menu links and Add a menu link for more details and options.

  • 3
    Menu yamls only help if you know in advance what menu items you want to create, Programmatic creation may be on node save. – Duncanmoo May 4 '17 at 8:04
  • 1
    How to add translatable menu item that way? Like one menu item, but in 3 languages (different menu item titles and paths). – MilanG Sep 10 '18 at 9:39
1

To expand on @skorzh answer and reply to the comment from @Matt, if you want to nest a menu item inside another you have to get the parent id and set it as 'parent'. As an example this code nests the item inside the top level using the variable $top_level below.

  $my_menu = \Drupal::entityTypeManager()->getStorage('menu_link_content')
    ->loadByProperties(['menu_name' => 'my-menu-name']);
  foreach ($my_menu as $menu_item) {
    $parent_id = $menu_item->getParentId();
    if (!empty($parent_id) {
      $top_level = $parent_id;
      break;
    }
  }
  $menu_link = MenuLinkContent::create([
    'title' => 'My menu link title',
    'link' => ['uri' => 'internal:/my/path'],
    'menu_name' => 'my-menu-name',
    'parent' => $top_level,
    'expanded' => TRUE,
    'weight' => 0,
  ]);
  $menu_link->save();

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.