Understanding the Menu API in Drupal
In Drupal 8 the menu system, in comparison to Drupal 7 has become much more flexible, and the areas of functionality are now separated into different systems.
The routing system now handles the following:
- Association of path with the Controller
- Combines access checking
- Parameter up-casting
- Serves as a basis for path access
The menu system is now a collection of:
- Different APIs for menu items
- Local tasks
- Contextual links defined by modules.
While we were working on one of our client's projects, we came across a requirement where we had to have an admin for every country and allow them to add and edit the details.
We decided to have the Country as a Vocabulary and the Countries as the terms in the vocabulary. The details of the Country are made available through fields in the vocabulary. Having done that, now we have every Country mapped to every Country admin. The term edit page should be made available to them as a menu link so that it’s easier to edit the details of the respective country, as shown in the screenshot below.
Defining Menu links
Menu links in Drupal 8 should be defined inside the module file following the convention module_name.links.menu.yml. Since menu-links are plugins themselves, they are discovered using the YAML discovery type.
Sample menu link definition:
Here the title key is required, and the route_name specifies the route the menu-link would point to.
By only specifying the parent link which is in a menu, we no longer need to mention the menu_name, as clearing the cache will get the menu link added to our menu.
Adding dynamic values to the menu link
With the use case that we discussed, we wanted to add a menu link to the edit page of a Country term that maps to the Country of the currently logged user.
The route to term edit page is entity.taxonomy_term.edit_form with the path /taxonomy/term/{taxonomy_term}/edit
Here the {taxonomy_term} is the route parameter that should be made available to the menu-link to switch paths dynamically.
To make this route parameter available dynamically, we need to extend the MenuLinkDefault class, containing the required information for the default interaction.
Providing the route parameters using the Menu Link plugin class
Using the getRouteParameters() function, we are passing the term id to the path - /taxonomy/term/{taxonomy_term}/edit
Now it’s available to the menu-link and changes dynamically when the user logs in.
Disabling menu-links dynamically
In the above example, we wanted to enable the menu-link only if the country value is present. Here, passing the empty string could lead to a page with a broken link.
So, we used the isEnabled() function to override the default functionality. Now, sending FALSE when the condition meets will disable the menu-link all together to the logged-in user.
This is one of the ways in which the menu-link could be altered dynamically. Other preferred methods could be to opt for hooks, commonly used hook_menu_links_discovered_alter() for statically defined menu-links, hook_link_alter to alter the parameters for links. Here is the list of hooks the Menu API had to offer.
Preethi Prabhakaran, PHP/Drupal Engineer - L2
A sanguine and all agog, you will find her watching world travel and crime documentaries in solitude when not at work. Propagating plants and laughing at her own mistakes, she is both a dilettante and a polymath.
Leave us a comment
Sirisha
I have a scenario where I need to show /hide dynamic menus dynamically based on user location.