An alternative to Menu Token module

An alternative to Menu Token module

I had some issues with Menu Token module, so I looked into an alternative. I found that there is an easy way to add dynamic components in menu links. Let's say that you are creating a web shop with Drupal Commerce and that you want to create a link to user's orders. The link would have to look something like this:

/user/{{ currentUserID }}/orders

As you can probably guess, {{ currentUserID }} is a dynamic component. Each user has a different ID. You can create such a link by creating two files inside your custom module.

First you need to create a my_module.links.menu.yml file in the root directory of your module:

my_module.user_orders:
  weight: -50
  menu_name: account
  class: Drupal\my_module\Plugin\Menu\UserOrdersMenuLink

As you can see this link will appear in the User account menu. The link path is generated in the UserOrdersMenuLink class. Let's see how that class looks like:

<?php

namespace Drupal\my_module\Plugin\Menu;

use Drupal\Core\Menu\MenuLinkDefault;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;

class UserOrdersMenuLink extends MenuLinkDefault {

  protected $currentUser;

  public function __construct(array $configuration, $plugin_id, $plugin_definition, StaticMenuLinkOverridesInterface $static_override, AccountInterface $current_user) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $static_override);

    $this->currentUser = $current_user;
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('menu_link.static.overrides'),
      $container->get('current_user')
    );
  }

  public function getTitle() {
    return $this->t('My Orders');
  }

  public function getUrlObject($title_attribute = TRUE) {
    return Url::fromUri('internal:/user/' . $this->currentUser->id() . '/orders');
  }

}

And that's it. Clear the cache and go to the user menu (/admin/structure/menu/manage/account). You should see your new dynamic link there.

Here is what your module directory structure should looks like:

My Module
├── my_module.info.yml
├── my_module.links.menu.yml
└── src
    └── Plugin
        └── Menu
            └── UserOrdersMenuLink.php

You may also like

2018 recap

As this year draws to an end and another one is only 24 hours away, I reflect on the best things that happened to me.