NOTE: This functionality is now available in Drupal 7 via the Breadcrumbs by Path or the Path Breadcrumbs modules. See differences here: #2012762: How does breadcrumbs_by_path compare with path_breadcrumbs module?

The following code will allow you to create a breadcrumb trail that matches the URL of the current page. For example, if the current URL is

http://www.example.com/photos/flowers/my_rose_garden

then the breadcrumb trail would be

Home > Photos > Flowers > My Rose Garden

This technique is best used on smaller sites as each part of the URL must point to a valid page, view, etc.

Add the following code to your theme's template.php file (make sure you replace [YOUR-THEME-NAME] with the name of your theme):

<?php
/**
 * Override theme_breadcrumb().
 */
function [YOUR-THEME-NAME]_breadcrumb($breadcrumb) {
  $links = array();
  $path = '';

  // Get URL arguments
  $arguments = explode('/', request_uri());

  // Remove empty values
  foreach ($arguments as $key => $value) {
    if (empty($value)) {
      unset($arguments[$key]);
    }
  }
  $arguments = array_values($arguments);

  // Add 'Home' link
  $links[] = l(t('Home'), '<front>');

  // Add other links
  if (!empty($arguments)) {
    foreach ($arguments as $key => $value) {
      // Don't make last breadcrumb a link
      if ($key == (count($arguments) - 1)) {
        $links[] = drupal_get_title();
      } else {
        if (!empty($path)) {
          $path .= '/'. $value;
        } else {
          $path .= $value;
        }
        $links[] = l(drupal_ucfirst($value), $path);
      }
    }
  }

  // Set custom breadcrumbs
  drupal_set_breadcrumb($links);

  // Get custom breadcrumbs
  $breadcrumb = drupal_get_breadcrumb();

  // Hide breadcrumbs if only 'Home' exists
  if (count($breadcrumb) > 1) {
    return '<div class="breadcrumb">'. implode(' &raquo; ', $breadcrumb) .'</div>';
  }
}
?>

Comments

fehin’s picture

Will this work for 5x?

BWPanda’s picture

It should, though I haven't tested it. A quick check of the functions shows they're all the same for Drupal 5 & 6.

chazz’s picture

Thanks! Does the job for me

GalloP’s picture

If i use this good script, when i click on a my primary links appear "?q="..

Someone know why?

Thanks

wernerglinka’s picture

This is a great script. However, the example will come out as:
Home > Photos > Flowers > My_rose_garden
To fix this one can add:
$value = str_replace("_", " ", $value);
just before
$links[] = l(drupal_ucfirst($value), $path);

AgaPe’s picture

better use

if( !isset($_REQUEST['q'])) {
  return '';
}
$arguments = explode('/', $_REQUEST['q']);

instead of
$arguments = explode('/', request_uri());
for use if your urls are with ?q=....

and i recommend to use the pathauto module to have links (and breadcrumbs using this snippet then) for example like "content/node-title" not "node/234"

Frederic wbase’s picture

Verry nice my friend, thanks for sharing!

http://www.wbase.be twitter: @wbase_be

Frederic wbase’s picture

I made a small adjustment to this code.

1. When the site is multilangual and you put the language in your path remove it from the breadcrumb
2. Check or the url is valid, when it is not valid (for example: special menu items) don't make a link from it.


/**
 * Return a themed breadcrumb trail.
 *
 * @param $breadcrumb
 *   An array containing the breadcrumb links.
 * @return a string containing the breadcrumb output.
 */
function phptemplate_breadcrumb($breadcrumb) {
$links = array();
  $path = '';

  // Get URL arguments
  if( !isset($_REQUEST['q'])) {
  return '';
    }
  $arguments = explode('/', $_REQUEST['q']);

  // Remove empty values
  foreach ($arguments as $key => $value) {
    if (empty($value)) {
      unset($arguments[$key]);
    }
  }
  $arguments = array_values($arguments);

  // Add 'Home' link
  $links[] = l(t('Home'), '<front>');

  // Add other links
  if (!empty($arguments)) {
    foreach ($arguments as $key => $value) {
      //remove language from breadcrumb
      dpm($value);
      switch ($value) {
        case 'nl':
          unset($value);
          break;
        case 'fr':
          unset($value);
          break;
        case 'en':
          unset($value);
          break;
        case 'de':
          unset($value);
          break;      
      }

      // Don't make last breadcrumb a link
      if ($key == (count($arguments) - 1)) {
        $links[] = drupal_get_title();
      } else {
        if (!empty($path)) {
          $path .= '/'. $value;
          dpm($path);
        } else {
          $path .= $value;
        }
        
      //Check if path is valid
        if (drupal_lookup_path('source', $path)) {
          $links[] = l(drupal_ucfirst($value), $path);
        } else {
          $links[] = drupal_ucfirst($value);
        }  
          

      }
    }
  }

  // Set custom breadcrumbs
  drupal_set_breadcrumb($links);

  // Get custom breadcrumbs
  $breadcrumb = drupal_get_breadcrumb();

  // Hide breadcrumbs if only 'Home' exists
  if (count($breadcrumb) > 1) {
    return '<div class="breadcrumb">'. implode('', $breadcrumb) .'</div>';
  }
}

http://www.wbase.be twitter: @wbase_be

Frederic wbase’s picture

I made another adjustment on the code so that the node title is printed instead of the value from the url

/**
 * Return a themed breadcrumb trail.
 *
 * @param $breadcrumb
 *   An array containing the breadcrumb links.
 * @return a string containing the breadcrumb output.
 */
function phptemplate_breadcrumb($breadcrumb) {
$links = array();
  $path = '';

  // Get URL arguments
  if( !isset($_REQUEST['q'])) {
  return '';
    }
  $arguments = explode('/', $_REQUEST['q']);

  // Remove empty values
  foreach ($arguments as $key => $value) {
    if (empty($value)) {
      unset($arguments[$key]);
    }
  }
  $arguments = array_values($arguments);

  // Add 'Home' link
  $links[] = l(t('Home'), '<front>');

  // Add other links
  if (!empty($arguments)) {
    foreach ($arguments as $key => $value) {
      //remove fr from breadcrumb
      
      if ($value == 'fr') {
        continue;
      }

      // Don't make last breadcrumb a link
      if ($key == (count($arguments) - 1)) {
        $links[] = drupal_get_title();
      } else {
        if (!empty($path)) {
          $path .= '/'. $value;
        } else {
          $path .= $value;
          $node=node_load(substr(drupal_get_normal_path($path), 5));
          $title=node_page_title($node);
        }
        //Check if path is valid
        if (drupal_lookup_path('source', $path)) {
          $links[] = l($title, $path);
        } else {
          $links[] = drupal_ucfirst($value);
        }
      }
    }
  }

  // Set custom breadcrumbs
  drupal_set_breadcrumb($links);

  // Get custom breadcrumbs
  $breadcrumb = drupal_get_breadcrumb();

  // Hide breadcrumbs if only 'Home' exists
  if (count($breadcrumb) > 1) {
    return '<div class="breadcrumb">'. implode(' &raquo; ', $breadcrumb) .'</div>';
  }
}

http://www.wbase.be twitter: @wbase_be

chrispooh’s picture

Hello, it is not working in d7 with ZEN subtheme. Can you help me?

webmens’s picture

I modified the code to suit my website (with image gallery). I'm sharing the code in case someone could use it.
Be sure to change the languages (if ($value == '[Place_language_code]') to the languages you use.

This code: Hides the language code, places the right links, makes all links clickable.

/**
* Return a themed breadcrumb trail.
*
* @param $breadcrumb
*   An array containing the breadcrumb links.
* @return a string containing the breadcrumb output.
*/
function [PLACE_THEME_NAME_HERE]_breadcrumb($breadcrumb) {
$links = array();
  $path = '';

  // Get URL arguments
  if( !isset($_REQUEST['q'])) {
  return '';
    }
  $arguments = explode('/', $_REQUEST['q']);

  // Remove empty values
  foreach ($arguments as $key => $value) {
    if (empty($value)) {
      unset($arguments[$key]);
    }
  }
  $arguments = array_values($arguments);

  // Add 'Home' link
  $links[] = l(t('Home'), '<front>');

  // Add other links
  if (!empty($arguments)) {
    foreach ($arguments as $key => $value) {
      //remove fr from breadcrumb
     
      if ($value == 'fr') {
        continue;
      }
	  
	  if ($value == 'Fr') {
        continue;
      }
	  
	  if ($value == 'nl') {
        continue;
      }
	  
	  if ($value == 'Nl') {
        continue;
      }
	  

      // Don't make last breadcrumb a link
      if ($key == (count($arguments) - 1)) {
        $links[] = drupal_get_title();
      } else {
        if (!empty($path)) {
          $path .= '/'. $value;
        } else {
          $path .= $value;
          $node=node_load(substr(drupal_get_normal_path($path), 5));
          $title=node_page_title($node);
        }
		
		//Place link
        $links[] = l(drupal_ucfirst($value), $path);
		
      }
    }
  }

  // Set custom breadcrumbs
  drupal_set_breadcrumb($links);

  // Get custom breadcrumbs
  $breadcrumb = drupal_get_breadcrumb();

  // Hide breadcrumbs if only 'Home' exists
  if (count($breadcrumb) > 1) {
    return '<div class="breadcrumb">'. implode(' &raquo; ', $breadcrumb) .'</div>';
  }
}
wfx’s picture

I have been looking for a breadcrumb snippet like this for so long and this is exactly what I need!

cesanford30’s picture

Flawless in 7.4 Thanks!

end user’s picture

Would be nice to be able to remove the current taxonomy/node name from the breadcrumb.

So if I at home >> products only home is showing.
Same if I'm at home >> products >> product foo don't show product foo in the breadcrumb as there's already a title for the page anyways.

vchen’s picture

I just want to say that I tested this with 7.12 on a sub-theme based on Bartik, and it still works beautifully! Just what I've been looking for in a long time! Thanks for providing the code and clear instructions!

BWPanda’s picture

I've just updated the page above with a link to the Breadcrumbs by Path module. It provides this functionality for Drupal 7 with no configuration necessary, just enable the module!

agileadam’s picture

And here's my version, which looks for the title of the page as it would show in the menu. I guess one could also add a fallback to look up the node title, as others have done. Note that menu_get_item() does load the entire node (if that's what you're viewing) within the page_arguments array (in $menu_item in this example). This all seems kind of inefficient... uggh.

/**
 * Override theme_breadcrumb().
 *
 * Base breadcrumbs on paths e.g., about/our-organization/bob-jones
 * turns into About Us > Our Organization > Bob Jones
 */
function itsomega_breadcrumb($breadcrumb) {
  $links = array();
  $path = '';
  $arguments = explode('/', request_uri());
  foreach ($arguments as $key => $value) {
    if (empty($value)) {
      unset($arguments[$key]);
    }
  }
  $arguments = array_values($arguments);

  $links[] = l(t('Home'), '<front>');

  if (!empty($arguments)) {
    foreach ($arguments as $key => $value) {
      if ($key == (count($arguments) - 1)) {
        $links[] = drupal_get_title();
      }
      else {
        if (!empty($path)) {
          $path .= '/'. $value;
        } else {
          $path .= $value;
        }

        $menu_item = menu_get_item(drupal_lookup_path('source', $path));
        if ($menu_item['title']) {
          $links[] = l($menu_item['title'], $path);
        }
        else {
          $links[] = l(ucwords(str_replace('-', ' ', $value)), $path);
        }
      }
    }
  }

  drupal_set_breadcrumb($links);
  $breadcrumb = drupal_get_breadcrumb();
  if (count($breadcrumb) > 1) {
    return '<div class="breadcrumb">'. implode(' &rsaquo; ', $breadcrumb) .'</div>';
  }
}
HannahMR’s picture

I just used this on a D6 site with a few minor changes…

I changed...

$links[] = l(drupal_ucfirst($value), $path);

to

$value = str_replace("-", " ", $value);
$links[] = l(ucwords($value), $path);

And added a few special cases via...

if (($arguments[0] == ‘path-one') || $arguments[0] == ‘path-two') {
$arguments[0] = ‘betterpath';
}

And it all worked great.
Thanks!