Keep the Current Page Out of the Breadcrumb Trail

Note: This guide is only valid for versions of Breadcrumb NavXT prior to 4.0. Since Breadcrumb NavXT 4.0 the bcn_after_fill action should be used to remove breadcrumbs from the breadcrumb trail.

Over the past year, several individuals have inquired on the feasibility of removing the current item (page, post, etc) from the Breadcrumb trail. While this is not good form, every page in the hierarchy should be represented in the breadcrumb trail, one will discuss how to remove the current item from the breadcrumb trail.

As in the Keep a Page Out of the Breadcrumb Trail guide, the method discussed herein differs from earlier methods provided in response to comments elsewhere. Likewise, this method uses the OOP principle of inheritance and requires PHP5–as does Breadcrumb NavXT so that should not be a problem.

Previously, removing the current item from the breadcrumb trail was the suggested method of implementation. While this works great, it does have some flexibility issues. And, it will not work if the bcn_breadcrumb_trail::trail array is a private or protected member variable (which may happen in the future). Instead, this guide will override the bcn_breadcrumb_trail::display() member function.

First, open the functions.php file of your theme. Within it we are going to create a new class named ext_breadcrumb_trail, and tell PHP that it is an extension of the bcn_breadcrumb_trail class. We will place the skeleton for the class constructor in at this time as well.

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	//Default constructor
	function __construct()
	{
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
}

Now, onto overriding bcn_breadcrumb_trail::display(). If you do not use bcn_breadcrumb_trail::display_trail() then this is all you will need:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	//Default constructor
	function __construct()
	{
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
	/**
	 * display
	 *
	 * Breadcrumb Creation Function
	 *
	 * This functions outputs or returns the breadcrumb trail in string form.
	 *
	 * @return void Void if Option to print out breadcrumb trail was chosen.
	 * @return string String-Data of breadcrumb trail.
	 * @param bool $return Whether to return data or to echo it.
	 * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not.
	 * @param bool $reverse[optional] Whether to reverse the output or not.
	 */
	function display($return = false, $linked = true, $reverse = false)
	{
		//Set trail order based on reverse flag
		$this->order($reverse);
		//Initilize the string which will hold the assembled trail
		$trail_str = '';
		//The main compiling loop
		foreach($this->trail as $key=>$breadcrumb)
		{
			//Must branch if we are reversing the output or not
			if($reverse)
			{
				//Add in the separator only if we are the 2nd or greater element
				if($key > 0)
				{
					$trail_str .= $this->opt['separator'];
				}
			}
			else
			{
				//Only show the separator when necessary
				if($key > count($this->trail) - 2)
				{
					$trail_str .= $this->opt['separator'];
				}
			}
			//Trim titles, if needed
			if($this->opt['max_title_length'] > 0)
			{
				//Trim the breadcrumb's title
				$breadcrumb->title_trim($this->opt['max_title_length']);
			}
			//We want to output everything but the current item
			if($key === 0)
			{
				break;
			}
			//Place in the breadcrumb's assembled elements
			$trail_str .= $breadcrumb->assemble($linked);
		}
		//Should we return or echo the assembled trail?
		if($return)
		{
			return $trail_str;
		}
		else
		{
			//Giving credit where credit is due, please don't remove it
			$tag = "<!-- Breadcrumb NavXT " . $this->version . " -->\n";
			echo $tag . $trail_str;
		}
	}
}

The above code has only minor changes from the distributed bcn_breadcrumb_trail::display() code. One line was adjusted so that one less breadcrumb separator would be output. The other change involved replacing $this->current_item($breadcrumb); with break;, ending the loop execution. Note, if you want the “extra” breadcrumb separator to still display, change the line:

if($key < count($this->trail) - 2)

to:

if($key < count($this->trail) - 1)

If you need bcn_breadcrumb_trail::display_trail() instead of bcn_breadcrumb_trail::display() you will want to use the following code:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	//Default constructor
	function __construct()
	{
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
	/**
	 * display_list
	 *
	 * Breadcrumb Creation Function
	 *
	 * This functions outputs or returns the breadcrumb trail in list form.
	 *
	 * @return void Void if Option to print out breadcrumb trail was chosen.
	 * @return string String-Data of breadcrumb trail.
	 * @param bool $return Whether to return data or to echo it.
	 * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not.
	 * @param bool $reverse[optional] Whether to reverse the output or not.
	 */
	function display_list($return = false, $linked = true, $reverse = false)
	{
		//Set trail order based on reverse flag
		$this->order($reverse);
		//Initilize the string which will hold the assembled trail
		$trail_str = '';
		//The main compiling loop
		foreach($this->trail as $key=>$breadcrumb)
		{
			$trail_str .= '
<li>';
			//Trim titles, if needed
			if($this->opt['max_title_length'] > 0)
			{
				//Trim the breadcrumb's title
				$breadcrumb->title_trim(
					$this->opt['max_title_length']);
			}
			//We want to output everything but the current item
			if($key === 0)
			{
				break;
			}
			//Place in the breadcrumb's assembled elements
			$trail_str .= $breadcrumb->assemble($linked);
			$trail_str .= "</li>

\n";
		}
		//Should we return or echo the assembled trail?
		if($return)
		{
			return $trail_str;
		}
		else
		{
			//Giving credit where credit is due, please don't remove it
			$tag = "<!-- Breadcrumb NavXT " . $this->version . " -->\n";
			echo $tag . $trail_str;
		}
	}
}

The only change in this code from the distributed bcn_breadcrumb_trail::display_trail() involved modifying the branch statement used for the current item. This involved replacing $this->current_item($breadcrumb); with break;. Now onto calling our new class. For users of the normal, sting output breadcrumb trail, you will use something on the lines of:

if(class_exists('ext_breadcrumb_trail'))
{
	//Make new instance of the ext_breadcrumb_trail object
	$breadcrumb_trail = new ext_breadcrumb_trail();
	//Setup options here if needed
	//Fill the breadcrumb trail
	$breadcrumb_trail->fill();
	//Display the trail
	$breadcrumb_trail->display();
}

While users of the HTML list output form of the breadcrumb trail will want to use:

if(class_exists('ext_breadcrumb_trail'))
{
	//Make new instance of the ext_breadcrumb_trail object
	$breadcrumb_trail = new ext_breadcrumb_trail();
	//Setup options here if needed
	//Fill the breadcrumb trail
	$breadcrumb_trail->fill();
	//Display the trail
	$breadcrumb_trail->display_list();
}

This is a quite simple method for removing the current item from the breadcrumb trail output. Since the display functions will not be modified in the foreseeable future, this is quite safe to use. Again, for usability reasons, one recommends you do not actually remove the current item from the breadcrumb trail.

-John Havlik

[end of transmission, stay tuned]

24 thoughts on “Keep the Current Page Out of the Breadcrumb Trail

  1. hi,

    very useful tutorial.
    i’ve been using your plugin and it works like a charm. however, i have a question about the above tutorial. what if i don’t want to remove the current page entirely, let’s say i want the categories there but not the post titles?

    in Single Page
    from:
    Home > Category1 > Post Title

    to:
    Home > Category1

    but everything remains the same in all other pages like in Category.
    Home > Category1

    let me know if my question is confusing :)
    thanks in advance!

    • Niña,

      Niña: what if i don’t want to remove the current page entirely, let’s say i want the categories there but not the post titles?

      Yeah, that would be more useful wouldn’t it :). You could replace

      //We want to output everything but the current item
      if($key === 0)
      {
      break;
      }

      with

      //We want to output everything but the current item
      if($key === 0)
      {
      if(is_single())
      {
      break;
      }
      $this-&gt;current_item($breadcrumb);
      }

      I think that should do the trick.

      -John Havlik

  2. What do you think about adding the parameter to the display function like so? And if I’m correct, the remove_current_page function should be able to handle if the $trail is private or protected?

    I cleaned up the display function too, to be cleaner…feel free to use if you want; I’m not sure if it accounts for all the possible params, but it’s pretty clear this way.

    function remove_current_page() {
    if (is_array($this->trail)) {
    unset($this->trail[0]);
    }
    }

    /**
    * display
    *
    * Breadcrumb Creation Function
    *
    * This functions outputs or returns the breadcrumb trail in string form.
    *
    * @return void Void if Option to print out breadcrumb trail was chosen.
    * @return string String-Data of breadcrumb trail.
    * @param bool $return Whether to return data or to echo it.
    * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not.
    * @param bool $reverse Whether to reverse the output of the trail
    * @param bool $show_current Whether to show the current page as part of the trail
    */
    function display($return = false, $linked = true, $reverse = false, $show_current = false) {
    //Set trail order based on reverse flag
    $this->order($reverse);

    // If we're not showing current page
    if (!$show_current) {
    $this->remove_current_page();
    }

    //The main compiling loop
    foreach($this->trail as $key => $breadcrumb) {

    //Trim titles, if needed
    if($this->opt['max_title_length'] > 0) {
    //Trim the breadcrumb's title
    $breadcrumb->title_trim($this->opt['max_title_length']);
    }

    //Place in the breadcrumb's assembled elements
    $trail_str[] = $breadcrumb->assemble($linked);
    }
    //Should we return or echo the assembled trail?
    if($return) {
    return implode($this->opt['separator'], $trail_str);
    }
    else {
    echo implode($this->opt['separator'], $trail_str);
    }
    }

    Thanks for your time making the plugin!

  3. Hi there,

    Tx for such wonderful plugin.

    I want to remove the last post title display in the breadcrumb. I tried something by reading above but can’t figure out.

    E.g. on this post
    http://www.smallbusinessdirectoryuk.co.uk/jobs/freelance-jobs.html

    I don’t want to display “Freelance Jobs” in the breadcrumb and only display
    Small Business Directory UK > Jobs

    Could you let me know how to get it done in simple steps?

    I tried to cooment out the code which is in following block but it didn’t work.
    if($key === 0) {…}

    • James,

      To be honest, on that page, from a usability and design standpoint I don’t see why you want to remove the current page/item from the breadcrumb trail. And, SEO wise, I have never seen Google punish anyone for keeping the current page title in the breadcrumb trail.

      That said, IIRC there is no need to be commenting out blocks of code (it’s been over three months since I wrote this article and I don’t remember the exact details). Following the article should yield the result that you desire. I can attach the ext_breadcrumb_class.php to the post if that’s needed, it may be later this week before that happens (I have school projects that are eating up my time at the moment).

      -John Havlik

  4. OK, for various reasons, I have a client that *only* wants the current item returned, nothing else in the trail.

    Suggestions as to how I could isolate and output that bit?

    thanks!

    Chuck

    • Chuck,

      If they want only the current item, then all they want it the page name. That isn’t a breadcrumb trail :), and can be done with standard WordPress theme functions.

      -John Havlik

      • Hey John,

        Thanks for the super rapid response.

        Right, but the page name will vary whether it is a page versus a post versus a category listing, and the breadcrumb class seems to intelligently “get” via the “current item,” whereas if I just call a page name function it will only work for pages, right?

        -Chuck

        • Chuck,

          Yeah each page type does titles differently. What you’ll end up needing is something like the bcn_breadcrumb_trail::fill to branch between the different page types, and then use the proper functions to find the names on the various types.

          If push comes to shove, you can always strip bcn_breadcrumb_trail::fill, and the necessary current item fillers from Breadcrumb NavXT and combine them for your title function. Using the entire Breadcrumb NavXT plugin will add overhead that you don’t need to incur. The code is well commented (a necessity for my own sanity as at times I may not get a chance to work on it for several months), and if you are proficient in PHP you shouldn’t have too may problems figuring out what I’m doing.

          -John Havlik

          • Hey John

            I have an issue similar to Chuck.

            I generate the current item already with theme functions and a certain formatting, different to what your plugin outputs.

            I’d like to remove the current_item from the string but keep the rest. I found a tutorial on your site that looks quite complicated for just removing the current_item.

            Is there a hack that completely removes it from the php?

            I know it’s not good practice but i will still generate it from theme.

            Thanks in advance
            fizzbacker

  5. Hi, I just installed this plugin and wanted to hide the current item.
    I managed to do the tric by filling ”current item prefix” with
    and ‘current item suffix’ with

    add a little css: span.noshow{display:none;}

    The “breadcrum separator” was left blank, and in “Catagory prefix” I filled in “»”

    This gives me a breadcrum like:
    “You are here: Home >> Category_name >> Sub_Category_name”
    The current item is then showed by the post’s title.

    • Jeroen,

      The problem with this method is that it will break for other post types (e.g. pages). Other than that, it will work the way you are doing it.

      -John Havlik

  6. sorry,

    this should read:
    current item prefix: <span class="noshow">
    suffix: </span>

    This did the trick for me

    Thanx for this great plugin!

  7. nice plugin. I have one question, how to disable the category link but still keep it displayed there?
    For example: Home>category>post. the title of the category is there you can not click it. How to make this work?

    • hafid,

      Not having the middle breadcrumbs linked makes having a breadcrumb trail pointless. Can it be done? Sure. Should you do it? No.

      That said, you just need to set the code>linked member variable to false for the breadcrumb object of the particular category.

      -John Havlik

  8. I Love the plug-in. Just installed it and was able to set it up really fast. The only problem is I don’t want breadcrumbs to appear on the home page. That’s the only page I don’t want it on. But I’m not a programmer so the above instructions are just causing my head to spin.

    What are the chances you’ll add an admin feature where someone can just check a check-box to not have this show up only on the home page? I’d think that would be a popular request you’ve gotten, but I may be unique in my request…

    • Alan,

      Disabling it on the home page is very, very simple to do. You just need to be familiar with WordPress conditionals. Just replace your calling code with the following:

      <?php
      if(!is_front_page() && function_exists('bcn_display'))
      {
      bcn_display();
      }
      ?>

      -John Havlik

  9. John-
    Great plugin, nicely done.

    I am not clear in this article (removing current page/item from the breadcrumb trail) how to include the code that calls the new class ext_breadcrumb_trail. Could you please explain further about where exactly this bit of code is to be placed? Thanks. –Bill

  10. Two things:

    1. Answered my own question (isn’t that just the way it goes…?)

    fill();
    //Display the trail
    $breadcrumb_trail->display();
    }
    ?>

    2. I realized that the tutorial’s display() function was probably from an earlier version of the Plugin. So for the code that goes into functions.php, I replaced the code for display() in the tutorial with the display() from the current version plugin’s breadcrumb_navxt_class.php file, and then made the changes relating to Current Item as described above.

    Works great!

  11. Sorry, my code got clipped in the last post. Essentially, I followed the tutorial and figured out where to place the calling code.

  12. Hi,
    i have just used the abode code, but i am having the following problems.
    1. The seperator is not shown at all
    2. It does not take the “Home Breadcrumb” that i have changed in the admin but it takes the default “Home”.

    Any sollution??

    Thank you for your great plugin!!
    Kostas

    • Kostas,

      Don’t use the above code with Breadcrumb NavXT 4.0 or newer, several things changed in 4.0 that causes the code covered in this guide to not work. Additionally, directly calling the bcn_breadcrumb_trail object, or a derived class means you’re on your own for passing in settings (the settings page does not affect what the trail will do).

      -John Havlik

  13. Hey guys…so this isnt exactly what this how to was for, but sorta related and in case you find this helpful I thought i’d share…for reasons i wont get in to, I needed to clip the first two parent pages of the breadcrumb and used the following code in an extension of the ‘bcn_breadcrumb_trail’ class. Not sure if it’s the most efficient way to do it but hey, it worked!

    So just for an example, my crumb trail was:

    Home > Parent 1 > Parent 2 > Parent 3

    I wanted it to be:
    Parent 2 > Parent 3

    So i did as follows:

    function order($reverse = false)
    {
    // Code to clip the trail array starts
    $trail = $this->trail;
    $trailcount = count($trail);
    $i=count($trail);
    $k=$i - 2;

    while($i > $k) {
    unset($trail[$i - 1]);
    $i--;
    };

    $this->trail = $trail;
    // ENDS

    if($reverse)
    {
    //Since there may be multiple calls our trail may be in a non-standard order
    ksort($this->trail);
    }
    else
    {
    //For normal opperation we must reverse the array by key
    krsort($this->trail);
    }
    }

Comments are closed.