Absolute menu links in Drupal 8

Creating absolute menu links in Drupal 8 is pretty simple, but it took a little thought to land on the best solution for my use case. I ran into the requirement while working with a client to deploy their site navigation to a REACT app sitting on a different domain. The menu links we pulled in from their primary website needed to point back to their domain correctly, which of course meant they needed to be absolute.

A quick search turned up a couple of solutions, but none that quite suited my requirements. Here’s what I came up with — it’s fairly concise, leaves the menu link attributes intact, and doesn’t involve the theme layer.

/**
 * Implements hook_preprocess_menu().
 *
 */
function MYTHEME_preprocess_menu(&$variables) {
  // Limit to specific menus for performance.
  $menus = ['main', 'footer'];
  if (isset($variables['menu_name']) && in_array($variables['menu_name'], $menus)) {
    MYTHEME_set_menu_items_to_absolute($variables['items']);
  }
}
 
/**
 * Recursively make menu items link with absolute.
 *
 */
function MYTHEME_set_menu_items_to_absolute(&$items) {
  foreach ($items as $item) {
    $url = $item['url'];
    if (!$url->isExternal()) {
      $item['url'] = $url->setOption('absolute', TRUE);
    }
    // Recursively loop of sub-menu items.
    if (isset($item['below'])) {
      MYTHEME_set_menu_items_to_absolute($item['below']);
    }
  }
}

Generating absolute menu links this way means I can pull main navigation onto various apps without any headache and without sacrificing any Drupal theme layer functionality.

You can download the gist here. Make sure you specify which menus you'd like to act on, by machine name, in the first line of the MYTHEME_preprocess_menu() function. The code goes in mytheme.theme — don't forget to replace MYTHEME with your theme name throughout.

Do you have a simpler way? Feel free to share in the comments.

Drupal Code

Read This Next