Description

Often, you need to know if a page (node, view or otherwise) has a menu item, and if so, what "level" of the menu it is on (level 1 being the top level menus, level 2 being the sub-menus, level 3 being the sub-sub menus etc). Once you determine this, you can style pages differently depending on their menu level.

  // Fetch the menu tree for the current page.
  $tree = menu_tree_page_data('primary-links');
  $level = 0;
  // Go down the active trail as far as possible.
  while ($tree) {
    // Loop through the current level's items until we find one that is in trail.
    while ($item = array_shift($tree)) {
      if ($item['link']['in_active_trail']) {
        // If the item is in the active trail, we count a new level.
        $level++;
        if (!empty($item['below'])) {
          // If more items are available, we continue down the tree.
          $tree = $item['below'];
          break;
        }
        // If we are at the end of the tree, our work here is done.
        break 2;
      }
    }
  }
  // Then, add body classes or other theme variables as needed:
  if ($level <= 2) {
    $vars['body_classes'] .= ' landing';
  }
  if ($level) {
    $vars['body_classes'] .= ' menu-level-' . $level;
  }

Notes

  • If you use another menu than "Primary Links" here, enter the menu name or ID instead of 'primary-links'.
  • The $vars['body_classes'] part assumes that this code is placed in your theme_preprocess_page() function in template.php, however the main logic should work pretty much anywhere.
  • This snippet will return 0 (zero) if the current page has no menu item in the requested menu - note that this can include the front page of the site. It is recommended that you use $vars['front_page'] (already generated) to specifically check for the front page.

Comments

pvasener’s picture

Anyone would know how to do the same thing in Drupal 8?

halth’s picture

I believe we could do something like this:

  /** @var \Drupal\Core\Menu\MenuActiveTrail $active_trail */
  $active_trail = \Drupal::service('menu.active_trail');
  
  // Replace `main` with the name of the menu you're working with.
  $menu_level = count($active_trail->getActiveTrailIds('main'));

--
Heitor Althmann
Drupal Developer