In this article we are going to see how to programmatically create a dynamic menu link. You'll encounter this issue in case you need to pass an argument to a menu link item. In Drupal core as is, it's impossible. The non-programmatic way of doing that would be to use menu token and insert your custom token in your link path. But what's going to interest us here is how to do it programmatically.
Let's assume we want to create a link so user can consult their profile on a custom path "/user/id/{user}/view".
The route
We will implement a custom route for this path in my_module.routing.yml:
my_module.my_route_name:
path: '/user/id/{user}/view'
defaults:
_title: 'View profile'
_controller: '\Drupal\my_module\Controller\MyController::content'
requirements:
_permission: 'access content'
options:
parameters:
user:
type: entity:user
Here our route leads to a Controller called MyController but it doesn't really matter as what we want to focus on is how to implement a menu link for this route.
The link
Then we will programmatically create our link. The Menu module implements a yml discovery plugin in Drupal\Core\Menu\MenuLinkBase and there is a default class for the default links: MenuLinkDefault. That's the one we are going to extend. But first, what we need to do is to set a custom class for our menu link definition in my_module.links.menu.yml.
my_module.my_link_name:
title: 'My title'
description: 'My link description.'
route_name: my_module.my_route_name
class: Drupal\my_module\Plugin\Menu\MyLinkNameMenuLink
menu_name: account
weight: -1
The trick resides here, in implementing a custom class for our link definition. Now we can override "getRouteParameters" method to return our path parameter, user here.
<?php
namespace Drupal\my_module\Plugin\Menu;
use Drupal\Core\Menu\MenuLinkDefault;
/**
* Declares a dynamic menu link to view user profile.
*/
class MyLinkNameMenuLink extends MenuLinkDefault {
/**
* {@inheritdoc}
*/
public function getRouteParameters() {
return [
'user' => \Drupal::currentUser()->id(),
];
}
}
That's it! Now a small cache clear and you should see your dynamic menu link in the account menu (menu_name: account).