Providing module-defined menu links
This documentation needs review. See "Help improve this page" in the sidebar.
Menu links are defined in static .yml files in modules. The naming of the .yml file is [MODULE MACHINE NAME].links.menu.yml.
Keys
Required
title- the text to be displayed for the menu item.
Optional
title_context- adds a context for translation. Useful if the value fortitleis something similar that could be accidentally translated when the title value is translated elsewhere in the system.description- the description of the menu item.route_name- used for internal links. The route name that the link points to. If this is not set, theurlkey must be set.url- used for external links. This must be a fully qualified URL. If this is not set, theroute_namekey must be set.parent- the plugin ID of the parent of the menu item.weight- the relative weight of the menu item. Items are listed in the menu by order of weight (lowest to highest), and if the weight is the same, alphabetically. The default is0(zero) when not set.enabled- whether or not the menu should be enabled by default.0(zero) is disabled,1(one) is enabled.route_parameters- for routes with dynamic components (ie - the user ID in theentity.user.canonicalroute), this value must be provided to build the link.menu_name- the machine name of the menu to which the menu item should be added. The default is the Tools menu (an optional administration menu).options- a series of options to be used when rendering the menu link. See \Drupal\Core\Url::fromUri() for more details.
Example
example.admin: # The plugin ID
title: 'Example settings'
description: 'Manage example settings for your site'
parent: system.admin_config_development
route_name: example.admin
weight: 100
# The menu link is enabled by default, we can override it with:
enabled: 0
route_parameters: { key: 'value' }
# If menu_name is omitted, the "Tools" menu will be used.
menu_name: devel
options:
query:
uid: 1
attributes:
target: _blank
class:
- some-class
- anotherclassThis example defines a local menu link so it uses a route_name to tie the menu link to a route. (External pointing menu links would use an url value). The description is shown either as a tooltip on the item or in the admin UI as the description of the option on the page. The weight is used to order the items (higher weights get placed towards the end of the menu among items on the same level). Finally, the item can be put into the menu hierarchy by referring to the parent menu link name. See further possible keys on the hook_menu_links_discovered_alter() documentation.
Determining the parent menu_link name can be a little tricky at first. If you know the path of the parent menu item, you would need to search for it in all available *.routing.yml files (most text editors and IDEs should allow you to search all files in a project) and find the route name for that path. Then, you would need to search for the route name in all available *.links.menu.yml files. The menu_link whose route_name matches is your link. Alternatively, if you know which module is defining the parent menu link (or one of the parent menu link's children), you can go straight to that module and perform your search (or you can see the available routes by http://www.example.com/devel/routes URL if devel module is installed).
Finally, you can provide string context for the menu link title in a title_context key, so if the link text is ambiguous (such as 'Extend', 'May', etc.) the string context helps translators pick the right translation. This is later passed on to t().
The route name for paths created by Views pages is in the format view.name.display_id.
Using anchor links
Anchor links in .menu.yml
example.anchor:
title: "Anchor example"
description: "Scroll to top on the current page"
url: "internal:#top"Altering menu links and adding menu links dynamically
Statically defined menu items may be altered using hook_menu_links_discovered_alter() (but note there is no hook_menu_link_discovered(), the menu links are built from the .yml files as explained above). This hook may also be used to add new dynamic menu items.
More often, you may want to use a deriver class to add new menu link plugins. For example, Views provided menu links are added in views.links.menu.yml, which specifies the deriver class \Drupal\views\Plugin\Derivative\ViewsMenuLink.
Finally, you can use the plugin manager directly to add, update, and remove definitions. For example, this creates a simplified version of the menu link at the top of the page:
$link_properties = ['title' => 'Example settings', 'route_name' => 'example.admin', 'menu_name' => 'devel', 'provider' => 'my_module'];
\Drupal::service('plugin.manager.menu.link')->addDefinition('example.admin', $link_properties);Please note that, to add a new definition this way, you should specify a value for the provider key. This value is the name of the module, providing the menu link.
A little change history...
The original replacement for menu links via hook_menu() was proposed to be called hook_default_menu_links() #2047633: Move definition of menu links to hook_menu_link_defaults(), decouple key name from path, and make 'parent' explicit, but that eventually changed to the method above hook_menu_link_defaults() moved to *.links.menu.yml files.
Routing
Refer to the routing system documentation on how to define the 'example.admin' route. The routing system will associate the path to a controller, while the menu system will make the item appear in the administration section.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion
Still on Drupal 7? Security support for Drupal 7 ended on 5 January 2025. Please visit our Drupal 7 End of Life resources page to review all of your options.