2

In Drupal 7, currently when I go to a user profile, the breadcrumbs go as follows: "Home > username."
I have a People section as part of my main navigation, so I would like the breadcrumbs to behave more like: "Home > People > username."

How can this be accomplished?

6

There are two possibilities: You can implement a hook in a module, or implement a theme function in the theme you are currently using.

Module

In Drupal 7, you can implement hook_menu_breadcrumb_alter(). The hook implementation receives the current breadcrumb array by reference, and the menu item for the currently visualized page. The example provided in the documentation page is the following one:

function hook_menu_breadcrumb_alter(&$active_trail, $item) {
  // Always display a link to the current page by duplicating the last link in
  // the active trail. This means that menu_get_active_breadcrumb() will remove
  // the last link (for the current page), but since it is added once more here,
  // it will appear.
  if (!drupal_is_front_page()) {
    $end = end($active_trail);
    if ($item['href'] == $end['href']) {
      $active_trail[] = $end;
    }
  }
}

An example of implementation of such hook could be the following one ("mymodule" needs to be replaced with the short name of the module that contains the hook):

function mymodule_menu_breadcrumb_alter(&$active_trail, $item) {
  if (substr($item['href'], 0, 4) == 'user') {
    // Add a trail item before the one linking to the user profile page.
  }
}

For a method that can be used on Drupal 6 too (when you want to develop code that is for both Drupal 6 and Drupal 7, and you don't want to write code for each Drupal version), you can use drupal_set_breadcrumb() to set the breadcrumb for the user profile pages.

An example of how the function can be called is the following Drupal function:

function blog_view($node, $view_mode) {
  if ($view_mode == 'full' && node_is_page($node)) {
    // Breadcrumb navigation.  l() escapes title, so we should not escape !name.
    drupal_set_breadcrumb(array(l(t('Home'), NULL), l(t('Blogs'), 'blog'), l(t("!name's blog", array('!name' => format_username($node))), 'blog/' . $node->uid)));
  }
  return $node;
}

You could alter the menu callback for the menu items associated with the user profiles, and use a menu callback that first sets the breadcrumb, and then calls the original menu callback. The hook to implement in this case is hook_menu_alter().

Theme

As far as I recall, a theme can also implement some alter hooks as a module does; alternatively, a theme just overrides a theme function ("mytheme" needs to be replaced with the short name of the theme).

function mytheme_breadcrumb($variables) {
    $breadcrumb = $variables['breadcrumb'];

    // Modify the breadcrumb.
}

The variable $breadcrumb is an array containing the HTML for the single parts of the breadcrumb. The default implementation of the theme function is the following one:

function theme_breadcrumb($variables) {
  $breadcrumb = $variables['breadcrumb'];

  if (!empty($breadcrumb)) {
    // Provide a navigational heading to give context for breadcrumb links to
    // screen-reader users. Make the heading invisible with .element-invisible.
    $output = '<h2 class="element-invisible">' . t('You are here') . '</h2>';

    $output .= '<div class="breadcrumb">' . implode(' » ', $breadcrumb) . '</div>';
    return $output;
  }
}

Between the two possible implementations, I would rather use a module, as it doesn't depend from the currently set theme; the theme can be changed, and the code would still change the breadcrumb. Generally, the code of a theme should alter the way elements are rendered, not to change the breadcrumb to alter the links it contains.

  • Does this also modify the active trail? – Lester Peabody Jul 28 '11 at 20:03
  • The active trail is all contained in the $active_trail array, which is passed by reference. – kiamlaluno Jul 28 '11 at 20:14
  • I guess I don't quite understand where I would place this function. Would this be in my template.php in the root of my theme, or somewhere else. I don't understand where the mymodule prefix comes in. – Lester Peabody Jul 28 '11 at 20:18
  • I expanded my answer. – kiamlaluno Jul 28 '11 at 21:07
  • I definitely like the module approach better myself. Reusable code = better code. However, I don't have any experience creating modules. If you could point me in the right direction as far as creating the most basic module necessary to run this code, that would be appreciated. Thanks for all of your help, you are a legend. – Lester Peabody Jul 29 '11 at 2:13
1

Check out the Menu position module.

Often times site builders want certain types of content to appear in a specific position in the navigational menu. The simplest solution, adding all of that content individually to the menu system, has performance and usability issues. (Imagine hundreds of menu items added to one spot in the menu.)

This module allows for the creation of rules that will dynamically add the current page into the menu system at the requested spots.

This includes affecting:

  • The main links of the theme
  • The secondary links of the theme
  • The breadcrumb trail
  • Menu blocks provided by core's Menu module
  • Menu blocks provided by the Menu Block module
1

I recently solved this problem in 10 minutes of sitebuilding with the Menu Position module.

One thing to keep in mind is that by default it doesn't allow positioning of user pages, just content types. However, you can "menu position" user pages by their path ("users/*").

This solves the breadcrumb problem and related contextual problems.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.