My BlogAbout MePortfolioTemplatesArticlesWeb StoreMessage Board (Forums)Guestbook

An easy way to display a customized menu in your Drupal theme

Submitted by Jakob on 3 February, 2007 - 01:07.My Blog | Drupal

I've been working on a theme where I needed to display a menu in Drupal given its menu id (mid), which is the unique identifier of the parent element of the menu's items. Usually, you can assign menus to different regions in your theme but the problem with that approach is that the menu will be rendered as a multi-level list (nested ULs). In this case, I wanted a flat list, and had written my own theme function to display the links on one line with delimiters, taking an array of menu items as argument. I ended up writing a function for this purpose using parts of the code from Drupal core, a function that others might find useful.

Menus in Drupal exist in a great hierarchy, a great menu tree, and menus are branches with twigs being the menu items. You can render any menu tree if you know the parent menu id of its menu items, these can easily be found by going to the Menu administration in your Drupal administration menu and hover with your mouse over the edit link next to a menu. Once you know this id, called mid, you can easily fetch its children, its menu items using the following function which you put in your template.php file. For some reason, there's no ready made function for this purpose in Drupal's core files, there's menu_get_menu() but it returns all menus and doesn't allow any filtering, which is why this function is required.


/** returns the child items of a menu */
function myfunc_get_menu_by_pid($pid) {
  $menu = menu_get_menu();
  $links = array();
  if ($pid && is_array($menu['visible'][$pid]) && isset($menu['visible'][$pid]['children'])) {
    $count = 1;
    foreach ($menu['visible'][$pid]['children'] as $cid) {
      $index = "menu-$start_level-$count-$pid";
      if (menu_in_active_trail_in_submenu($cid, $pid)) {
        $index .= "-active";
      }
      $links[$index] = menu_item_link($cid, FALSE);
      $count++;
    }
  }
  return $links;
}

The function above returns an array with menu items, which are arrays themselves. To render it as html, use the following function, called a theme function override, in your template.php file. You need to rename this function nameofyourtheme_links_flat, where nameofyourtheme is the name of your theme, obviously :)


/** generate footer links  */
function nameofyourtheme_links_flat($links, $delimiter = ' | ') {
  $linkshtml = array();
  if (!is_array($links)) {
    return '';
  }
  foreach ($links as $key => $link) {
  	
     $linkshtml[] = l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment'], FALSE, $html);
 	
  }
  return implode($delimiter, $linkshtml);
}

To print the HTML in your theme, you can do one of the following. Either add this to your template file (page.tpl.php for example), where 45 is the mid of the menu:



<?php print theme( 'links_flat', myfunc_get_menu_by_pid(45) ) ?>

or place the code above in a customized Drupal block, with input type "PHP Code", a block you can then assign to any region you like. The second method is the best in my opinion as it lets you change menu to fetch menu items from without having to edit your template files.

Easy as pie! If you have a question, post a comment below and I'll answer it as soon as I can.



Trackback URL for this post:

http://www.jakob-persson.com/trackback/535

Reply



The content of this field is kept private and will not be shown publicly.


*

  • Web and e-mail addresses are automatically converted into links.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
Verify comment authorship
Captcha Image: you will need to recognize the text in it.
*
Please type in the letters/numbers that are shown in the image above.