Overriding a menu in a block or template file

Last updated on
20 May 2017

Menu Links

For Drupal 7, in almost all themes, menu links are displayed by calling theme('links__system_main_menu'). However, if you search for this specific function in Drupal API, you will not find it, and may be confused.

The answer to the confusion is that links__system_main_menu is not an actual function, but a pattern. A pattern, like page__article. In this pattern, the theming engine will look for this theme_... function, and if not found, it will use the standard theme('links') from the theme.inc file. This is what happens in most cases, when this function is called when rendering your menu.

You can override that function from your theme's template.php file.

Create an override function in your theme's template.php file:

<?php function themename_links__system_MENUNAME_menu($variables) {} ?>

MENUNAME is obtainable by editing the menu. It is the machine name of the menu with dashes converted to underscores.

The $variables parameter is passed in, and it contains an index called 'links'. Each link contains an 'href' and a 'title', among other things.

So inside your override function, loop over the links:

<?php foreach ($variables['links'] as $link) {}?>

If we just want to output an <a> tag, outside of Drupal we'd normally do:
<?php echo "<a href="{$link['href']}">{$link['title']}</a>"; ?>

However, Drupal has the l() function to create links for you. This is preferable because there are some special cases such as the <front> link.

So instead, we'd do something like
<?php echo l($link['title'], $link['href'], $link); ?>

The l() function will take care of adding an active class to a link if that link is to the page currently being viewed.

Your final function might look something like:

<?php
function THEMENAME_links__system_MENUNAME_menu($variables) {
  $output = '';
  foreach ($variables['links'] as $link) {
    $output .= l($link['title'], $link['href'], $link);
  }
  return $output;
}
?>

Menu itself

In order to theme the ul tags of the menu, you need to use the theme_menu_tree() function. An example would be (template.php):

function THEMENAME_menu_tree__MENUNAME($variables) {
  return '<ul class="menu">' . $variables['tree'] . '</ul>';
}

The above would append myclass to the classes of all ul tags of the MENUNAME. In order to theme the top level tag only, you would:

function THEMENAME_menu_tree__menu_top_menu($variables) {
 return '<ul class="menu">' . $variables['tree'] . '</ul>';
}