I need to add some links to existing menu (or to new) programmatically in Drupal 8.
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();
-
1entity_create is deprecated. Use \Drupal::entityTypeManager()->get storage('menu')-create([]); – Eyal Apr 6 '16 at 11:47
-
1
-
3
-
11Would 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
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.
-
3Menu 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
-
1How 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
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();