Menu and routing system

  1. 7.x drupal/includes/menu.inc menu
  2. 5.x drupal/includes/menu.inc menu
  3. 6.x drupal/includes/menu.inc menu
  4. 8.x drupal/core/includes/menu.inc menu

Define the navigation menus, and route page requests to code based on URLs.

Overview and terminology

The Drupal routing system defines how Drupal responds to URL requests that the web server passes on to Drupal. The routing system is based on the Symfony framework. The central idea is that Drupal subsystems and modules can register routes (basically, URL paths and context); they can also register to respond dynamically to routes, for more flexibility. When Drupal receives a URL request, it will attempt to match the request to a registered route, and query dynamic responders. If a match is made, Drupal will then instantiate the required classes, gather the data, format it, and send it back to the web browser. Otherwise, Drupal will return a 404 or 403 response.

The menu system uses routes; it is used for navigation menus, local tasks, local actions, and contextual links:

  • Navigation menus are hierarchies of menu links; links point to routes or URLs.
  • Menu links and their hierarchies can be defined by Drupal subsystems and modules, or created in the user interface using the Menu UI module.
  • Local tasks are groups of related routes. Local tasks are usually rendered as a group of tabs.
  • Local actions are used for operations such as adding a new item on a page that lists items of some type. Local actions are usually rendered as buttons.
  • Contextual links are actions that are related to sections of rendered output, and are usually rendered as a pop-up list of links. The Contextual Links module handles the gathering and rendering of contextual links.

The following sections of this topic provide an overview of the routing and menu APIs. For more detailed information, see https://www.drupal.org/developing/api/8/routing and https://www.drupal.org/developing/api/8/menu

Registering simple routes

To register a route, add lines similar to this to a module_name.routing.yml file in your top-level module directory:

dblog.overview:
  path: '/admin/reports/dblog'
  defaults:
    _content: '\Drupal\dblog\Controller\DbLogController::overview'
    _title: 'Recent log messages'
  requirements:
    _permission: 'access site reports'

Some notes:

  • The first line is the machine name of the route. Typically, it is prefixed by the machine name of the module that defines the route, or the name of a subsystem.
  • The 'path' line gives the URL path of the route (relative to the site's base URL).
  • The 'defaults' section tells how to build the main content of the route, and can also give other information, such as the page title and additional arguments for the route controller method. There are several possibilities for how to build the main content, including:

  • The 'requirements' section is used in Drupal to give access permission instructions (it has other uses in the Symfony framework). Most routes have a simple permission-based access scheme, as shown in this example. See the Permission system topic for more information about permissions.

See https://www.drupal.org/node/2092643 for more details about *.routing.yml files, and https://www.drupal.org/node/2122201 for information on how to set up dynamic routes.

Defining routes with placeholders

Some routes have placeholders in them, and these can also be defined in a module_name.routing.yml file, as in this example from the Block module:

block.admin_edit:
  path: '/admin/structure/block/manage/{block}'
  defaults:
    _entity_form: 'block.default'
    _title: 'Configure block'
  requirements:
    _entity_access: 'block.update'

In the path, '{block}' is a placeholder - it will be replaced by the ID of the block that is being configured by the entity system. See the Entity API topic for more information.

Route controllers for simple routes

For simple routes, after you have defined the route in a *.routing.yml file (see Registering simple routes above), the next step is to define a page controller class and method. Page controller classes do not necessarily need to implement any particular interface or extend any particular base class. The only requirement is that the method specified in your *.routing.yml file return one of the following, depending on whether you specified _content or _controller in the routing file defaults section:

As a note, if your module registers multiple simple routes, it is usual (and usually easiest) to put all of their methods on one controller class.

Most controllers will need to display some information stored in the Drupal database, which will involve using one or more Drupal services (see the Services and container topic). In order to properly inject services, a controller should implement \Drupal\Core\DependencyInjection\ContainerInjectionInterface; simple controllers can do this by extending the \Drupal\Core\Controller\ControllerBase class. See \Drupal\dblog\Controller\DbLogController for a straightforward example of a controller class.

Routes for administrative tasks can be added to the main Drupal administrative menu hierarchy. To do this, add lines like the following to a module_name.links.menu.yml file (in the top-level directory for your module):

dblog.overview:
  title: 'Recent log messages'
  parent: system.admin_reports
  description: 'View events that have recently been logged.'
  route_name: dblog.overview
  weight: -1

Some notes:

  • The first line is the machine name for your menu link, which usually matches the machine name of the route (given in the 'route_name' line).
  • parent: The machine name of the menu link that is the parent in the administrative hierarchy. See system.links.menu.yml to find the main skeleton of the hierarchy.
  • weight: Lower (negative) numbers come before higher (positive) numbers, for menu items with the same parent.

Menu items from other modules can be altered using hook_menu_link_defaults_alter().

@todo Derivatives will probably be defined for these; when they are, add documentation here.

Defining groups of local tasks (tabs)

Local tasks appear as tabs on a page when there are at least two defined for a route, including the base route as the main tab, and additional routes as other tabs. Static local tasks can be defined by adding lines like the following to a module_name.links.task.yml file (in the top-level directory for your module):

book.admin:
  route_name: book.admin
  title: 'List'
  base_route: book.admin
book.settings:
  route_name: book.settings
  title: 'Settings'
  base_route: book.admin
  weight: 100

Some notes:

  • The first line is the machine name for your local task, which usually matches the machine name of the route (given in the 'route_name' line).
  • base_route: The machine name of the main task (tab) for the set of local tasks.
  • weight: Lower (negative) numbers come before higher (positive) numbers, for tasks on the same base route. If there is a tab whose route matches the base route, that will be the default/first tab shown.

Local tasks from other modules can be altered using hook_menu_local_tasks_alter().

@todo Derivatives are in flux for these; when they are more stable, add documentation here.

Defining local actions for routes

Local actions can be defined for operations related to a given route. For instance, adding content is a common operation for the content management page, so it should be a local action. Static local actions can be defined by adding lines like the following to a module_name.links.action.yml file (in the top-level directory for your module):

node.add_page:
  route_name: node.add_page
  title: 'Add content'
  appears_on:
    - system.admin_content

Some notes:

  • The first line is the machine name for your local action, which usually matches the machine name of the route (given in the 'route_name' line).
  • appears_on: Machine names of one or more routes that this local task should appear on.

Local actions from other modules can be altered using hook_menu_local_actions_alter().

@todo Derivatives are in flux for these; when they are more stable, add documentation here.

Defining contextual links

Contextual links are displayed by the Contextual Links module for user interface elements whose render arrays have a '#contextual_links' element defined. For example, a block render array might look like this, in part:

array(
  '#contextual_links' => array(
    'block' => array(
      'route_parameters' => array('block' => $entity->id()),
    ),
  ),

In this array, the outer key 'block' defines a "group" for contextual links, and the inner array provides values for the route's placeholder parameters (see Defining routes with placeholders above).

To declare that a defined route should be a contextual link for a contextual links group, put lines like the following in a module_name.links.contextual.yml file (in the top-level directory for your module):

block_configure:
  title: 'Configure block'
  route_name: 'block.admin_edit'
  group: 'block'

Some notes:

  • The first line is the machine name for your contextual link, which usually matches the machine name of the route (given in the 'route_name' line).
  • group: This needs to match the link group defined in the render array.

Contextual links from other modules can be altered using hook_contextual_links_alter().

@todo Derivatives are in flux for these; when they are more stable, add documentation here.

Functions

Namesort descending Location Description
hook_contextual_links_alter drupal/core/modules/system/system.api.php Alter contextual links before they are rendered.
hook_menu_link_defaults_alter drupal/core/modules/system/system.api.php Alter links for menus.
hook_menu_local_actions_alter drupal/core/modules/system/system.api.php Alter local actions plugins.
hook_menu_local_tasks_alter drupal/core/modules/system/system.api.php Alter tabs and actions displayed on the page before they are rendered.
menu_cache_clear_all drupal/core/includes/menu.inc Clears all cached menu data.
menu_delete_links drupal/core/includes/menu.inc Deletes all links for a menu.
menu_get_active_menu_names drupal/core/includes/menu.inc Gets the active menu for the current page.
menu_get_local_actions drupal/core/includes/menu.inc Returns the rendered local actions at the current level.
menu_link_get_preferred drupal/core/includes/menu.inc Looks up the preferred menu link for a given system path.
menu_link_rebuild_defaults drupal/core/includes/menu.inc Builds menu links for the items returned from the menu_link.static service.
menu_list_system_menus drupal/core/includes/menu.inc Returns an array containing the names of system-defined (default) menus.
menu_load_links drupal/core/includes/menu.inc Returns an array containing all links for a menu.
menu_local_tabs drupal/core/includes/menu.inc Returns a renderable element for the primary and secondary tabs.
menu_local_tasks drupal/core/includes/menu.inc Collects the local tasks (tabs), action links, and the root path.
menu_main_menu drupal/core/includes/menu.inc Returns an array of links to be rendered as the Main menu.
menu_navigation_links drupal/core/includes/menu.inc Returns an array of links for a navigation menu.
menu_primary_local_tasks drupal/core/includes/menu.inc Returns the rendered local tasks at the top level.
menu_reset_static_cache drupal/core/includes/menu.inc Resets the menu system static cache.
menu_secondary_local_tasks drupal/core/includes/menu.inc Returns the rendered local tasks at the second level.
menu_secondary_menu drupal/core/includes/menu.inc Returns an array of links to be rendered as the Secondary links.
menu_set_active_menu_names drupal/core/includes/menu.inc Sets (or gets) the active menu for the current page.
menu_tab_root_path drupal/core/includes/menu.inc Returns the router path, or the path for a default local task's parent.
template_preprocess_menu_tree drupal/core/includes/menu.inc Implements template_preprocess_HOOK() for theme_menu_tree().
theme_menu_link drupal/core/includes/menu.inc Returns HTML for a menu link and submenu.
theme_menu_local_action drupal/core/includes/menu.inc Returns HTML for a single local action link.
theme_menu_local_task drupal/core/includes/menu.inc Returns HTML for a single local task link.
theme_menu_local_tasks drupal/core/includes/menu.inc Returns HTML for primary and secondary local tasks.
theme_menu_tree drupal/core/includes/menu.inc Returns HTML for a wrapper for a menu sub-tree.
_menu_get_links_source drupal/core/includes/menu.inc Returns the source of links of a menu.
_menu_item_localize drupal/core/includes/menu.inc Localizes a menu link title using t() if possible.
_menu_link_save_recursive drupal/core/includes/menu.inc Saves menu links recursively for menu_links_rebuild_defaults().
_menu_link_translate drupal/core/includes/menu.inc Provides menu link unserializing, access control, and argument handling.
_menu_set_expanded_menus drupal/core/includes/menu.inc Updates a list of menus with expanded items.
_menu_update_expanded_menus drupal/core/includes/menu.inc Updates the expanded menu item state at most twice per page load.

Constants

Namesort descending Location Description
MENU_MAX_DEPTH drupal/core/includes/menu.inc The maximum depth of a menu links tree - matches the number of p columns.
MENU_PREFERRED_LINK drupal/core/includes/menu.inc Reserved key to identify the most specific menu link for a given path.

Classes

Namesort descending Location Description
ControllerBase drupal/core/lib/Drupal/Core/Controller/ControllerBase.php Utility base class for thin controllers.

Interfaces

Namesort descending Location Description
ContainerInjectionInterface drupal/core/lib/Drupal/Core/DependencyInjection/ContainerInjectionInterface.php Defines a common interface for route controllers.
HtmlFragmentInterface drupal/core/lib/Drupal/Core/Page/HtmlFragmentInterface.php A domain object for a portion of an HTML page, including related data.

File

drupal/core/includes/menu.inc, line 12
API for the Drupal menu system.