- Drupal 9 Module Development
- Daniel Sipos Antonio De Marco
- 708字
- 2021-06-11 18:36:07
Working with menu links
Now that we know how to load and manipulate trees of menu links, let's talk a bit more about the regular menu links. In this section, we will look at how our module can define menu links and how we can work with them programmatically once we get our hands on them from a tree or somewhere else.
Defining menu links
In our Hello World module, we defined a couple of routes, one of which maps to the /hello path. Let's now create a link to that path that goes inside the main menu that is shipped with Drupal core.
As I mentioned, menu links are defined inside a *.links.menu.yml file. So, let's create that file for our module and add our menu link definition in it:
hello_world.hello:
title: 'Hello'
description: 'Get your dynamic salutation.'
route_name: hello_world.hello
menu_name: main
weight: 0
In a typical YAML notation, we have the machine name (in this case, also the plugin ID) hello_world.hello, followed by the relevant information below it. These are the most common things you will define for a menu link:
- The title is the menu link title whereas the description is, by default, set as the title attribute on the resulting link tag.
- The route_name indicates the route to be used behind this link.
- The menu_name indicates the menu that it should be in; this is the machine name of the menu.
- The weight can be used to order links within the menu.
- parent can be used to indicate another menu link the current one should be a child of (as such, you can build the hierarchy).
Once this is in, you should clear the cache and check out the links in the menu. You'll note that you can edit it, but some things cannot be changed through the UI due to them being defined in code.
Note that links that are created as a result of plugin derivatives, such as the ones created in the UI, have machine names (plugin IDs) in the following format:
main_plugin_id:plugin_derivative_id
The main_plugin_id is the ID of the menu link plugin that is responsible for deriving multiple links, whereas the plugin_derivative_id is the ID given to each inpidual derivative. For example, in the case of MenuLinkContent entities, the format is like this:
menu_link_content:867c544e-f1f7-43aa-8bf7-22fcb08a4b50
The UUID in this example is actually the UUID of the menu link content entity, which happens to be the plugin derivative ID.
Manipulating menu links
I mentioned earlier that MenuLinkTreeElement objects wrap inpidual menu links, but what can you do with these programmatically if you choose to work with this data yourself and not rely on the menu theme hook? Let's cover a few common things you can do.
First of all, the most important thing to do is to access the menu link plugin. You can do so directly, as it is a public property on the MenuLinkTreeElement:
$link = $data->link;
Now, you can work with the $link variable, which is an instance of MenuLinkInterface, and more often than not, an actual MenuLinkDefault instance that extends the MenuLinkBase class.
So if we inspect that interface, we can see a number of handy methods. The most common of these will be the getters for the menu link definition we saw earlier when defining the plugins. The getUrlObject() is also an important method that transforms the route of the menu link into a Url object that we already know how to use. If the menu link is created in the UI, it could be that it has no route but only a path, in which case, this method will still be able to construct a common Url object based on that path.
If you have your hands on a menu link that is not from a tree where you have already handled access, you can ask the Url object to check access before actually using it:
$access = $url->access();
If the link is not routed, the access will always return TRUE because it means that the link is external, or, in any case, no access check can be done. We will talk more about the access system in Chapter 10, Access Control.