Create a dynamic menu link

Submitted by victor.bourgade on

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).

Oznake

Drupal 8 Drupal 9 menu

About the writer

victor.bourgade

Victor is a web developer passionnated in drupal and bootstrap technologies. He likes challenges and beautiful designs.

When not behind his computer you'll find him drinking beers with friends or in the middle of nowhere hiking with his dog.