Keep a 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.

In the past, several users have asked how to exclude certain pages from the breadcrumb trail generated by Breadcrumb NavXT. As with most programming problems, many solutions exist to this problem. Previously, one posted code that removed the breadcrumb from the bcn_breadcrumb_trail::trail array before calling bcn_breadcrumb_trail::display(). However, since the introduction of Breadcrumb NavXT 3.0 a much better solution exists. This method uses the inheritance principle of OOP and requires no editing of the distributed files.

Code in this tutorial was written against the SVN Trunk version of Breadcrumb NavXT (the basis or Breadcrumb NavXT 3.3.0). Therefore, any code contained herein will require some modifications to work with Breadcrumb NavXT 3.2.x. The general process, however, is the same for any version of Breadcrumb NavXT since 3.0.0. Also, note that you must have a PHP5 environment for this to work as it requires the PHP5 object model.

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’ll 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();
	}
}

We need a way to get the IDs that will be excluded from the trail into the class. They could be hard coded into the class, but that is not very extensible (and a very bad coding practice). Instead, a public member variable named $excluded_ids will be added to store the IDs. Now, we should have the constructor accept IDs to exclude and store them in $excluded_ids. Our code now looks similar to the following:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	public $excluded_ids = array();
	//Default constructor
	function __construct($excluded_ids)
	{
		//Set the value of
		$this->excluded_ids = $excluded_ids;
		//Need to make sure we call the constructor of bcn_breadcrumb_trail
		parent::__construct();
	}
}

Now that the IDs of pages to be excluded can get into the class, we need to do something with them. We want to override the function bcn_breadcrumb_trail::page_parents() since it does not know how to exclude pages. To start, we’ll copy the code for page_parents from the class bcn_breadcrumb_trail into our new class. This is the result:

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	public $excluded_ids = array();
	function __construct($excluded_ids)
	{
		$this->excluded_ids = $excluded_ids;
		parent::__construct();
	}
	/**
	 * page_parents
	 *
	 * A Breadcrumb Trail Filling Function
	 *
	 * This recursive functions fills the trail with breadcrumbs for parent pages.
	 * @param  (int)   $id The id of the parent page.
	 * @param  (int)   $frontpage The id of the front page.
	 */
	function page_parents($id, $frontpage)
	{
		$parent = get_post($id);
		//Place the breadcrumb in the trail, uses the constructor
		$breadcrumb = $this->add(new bcn_breadcrumb(apply_filters('the_title', $parent->post_title), $this->opt['page_prefix'], $this->opt['page_suffix']));
		//Assign the anchor properties
		$breadcrumb->set_anchor($this->opt['page_anchor'], get_permalink($id));
		//Make sure the id is valid
		if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
		{
			//If valid, recursively call this function
			$this->page_parents($parent->post_parent, $frontpage);
		}
	}
}

Now, it’s time to modify the page_parents() function. We’ll use ext_breadcrumb_trail::excluded_ids and the PHP function in_array() to skip the breadcrumb insertion step for pages that are to be excluded from the trail. We do this by wrapping the two lines of code containing the variable $breadcrumb within a branch of an if statement. Within the if statement we’ll use $id and $this->excluded_ids as the parameters for in_array(). Since we want the branch to run if the ID is not an excluded ID, we’ll place the not operator (!) in front of in_array. At this point, we have the final version of our class that is ready to use.

class ext_breadcrumb_trail extends bcn_breadcrumb_trail
{
	public $excluded_ids = array();
	function __construct($excluded_ids)
	{
		$this->excluded_ids = $excluded_ids;
		parent::__construct();
	}
	/**
	 * page_parents
	 *
	 * A Breadcrumb Trail Filling Function
	 *
	 * This recursive functions fills the trail with breadcrumbs for parent pages.
	 * @param  (int)   $id The id of the parent page.
	 * @param  (int)   $frontpage The id of the front page.
	 */
	function page_parents($id, $frontpage)
	{
		$parent = get_post($id);
		//Check if the current page should be excluded
		if(!in_array($id, $this->excluded_ids))
		{
			//Place the breadcrumb in the trail, uses the constructor
			$breadcrumb = $this->add(new bcn_breadcrumb(apply_filters('the_title', $parent->post_title), $this->opt['page_prefix'], $this->opt['page_suffix']));
			//Assign the anchor properties
			$breadcrumb->set_anchor($this->opt['page_anchor'], get_permalink($id));
		}
		//Make sure the id is valid
		if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent)
		{
			//If valid, recursively call this function
			$this->page_parents($parent->post_parent, $frontpage);
		}
	}
}

Next, we need to modify the breadcrumb trail calling code in the theme. Assuming that the theme directly calls the bcn_breadcrumb_trail class, very little has to be modified. We just replace all instances of bcn_breadcrumb_trail with ext_breadcrumb_trail in the calling code. Additionally, when creating the new instance of ext_breadcrumb_trail we need to feed in our array of IDs of pages to be excluded. An example calling code block is located below, in it pages with ID equal to 100, 230, or 231 will not show up in the breadcrumb trail except when they are the current page.

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

In this tutorial we never modified any of the actual plugin files. This was made possible due to inheritance through the creation of a derived class. Since no plugin files were modified, upgrading to new versions of Breadcrumb NavXT are less likely to break the functionality. Finally, this method can easily be modified to exclude categories instead of pages from the breadcrumb trail (replace page_parents with category_parents).

-John Havlik

[end of transmission, stay tuned]

Trackbacks/Pingbacks

  1. Pingback: Keep the Current Page Out of the Breadcrumb Trail | Mtekk's Crib

42 thoughts on “Keep a Page Out of the Breadcrumb Trail

  1. Hello there,

    Firstly, thankyou for a brilliant plugin :) an elegant solution indeed. However, I followed this tutorial in an attempt to remove one page from the trail. All was working well untill I noticed this area on one page of my site:

    Fatal error: Call to undefined method ext_breadcrumb_trail::add() in /var/www/stillsharpmusic/wp-content/themes/wu-wei/functions.php on line 109

    And line 102 to 115 in my function.php are:

    function page_parents($id, $frontpage)
    {
    $parent = get_post($id);
    //Check if the current page should be excluded
    if(!in_array($id, $this->excluded_ids))
    {
    //Place the breadcrumb in the trail, uses the constructor
    $breadcrumb = $this->add(new bcn_breadcrumb(
    apply_filters(‘the_title’, $parent->post_title),
    $this->opt[‘page_prefix’], $this->opt[‘page_suffix’]));
    //Assign the anchor properties
    $breadcrumb->set_anchor($this->opt[‘page_anchor’],
    get_permalink($id));
    }

    This happens on a particular page upon clicking a child page link. This page is not the one being excluded from the breadcrumbs. I have another similar page with children yet it works perfectly well on that one :s

    I hope you can help
    Many thanks
    Dan

    • Dan,

      What version of Breadcrumb NavXT and PHP are you running? If ext_breadcrumb_trail::add() is missing, then either inheritance is not working correctly (possibly due to a bug in old PHP5 versions (5.0.x)) or breadcrumb_trail::add() is missing, which means your Breadcrumb NavXT version is not from the SVN Trunk.

      -John Havlik

  2. Oops, forgot to mention that line 109 is:

    $breadcrumb = $this->add(new bcn_breadcrumb(

    Cheers
    Dan

  3. Hmm, interesting… I have fixed my problem, yet in an odd way. Basically if the page containing the children is not one of the pages being excluded from the breadcrumb, then the error appears. If the page containing the children is being excluded then everything displays fine… This is ok for my situation as I don’t want the childs parent to be displayed in both cases.

    I hope this helps in bugfixing etc

    Cheers
    Dan

  4. Thanks, John. This is what I am looking for — except with categories. Are you saying to just replace instances of “page_parents” with “category_parents” in the code above? If so, it doesn’t seem to be working for me — am I missing something?

    • Courtney,

      What you have to do is copy over the category_parents function and modify it in a similar manner as was done to page_parents in the above example. Just copying and pasting it won’t do any good as your overriding function is the exact same as the original function.

      -John Havlik

  5. Ah, got it. I have it working — but I do have a question:

    Let’s say this is my breadcrumb trail:

    Home > Blog Page > Category 1 > Category 2 > Post

    I can now easily remove Category 1 and Category 2 — but how can I remove Blog Page? Because it’s not a category.

  6. Hey John, trying to get this tutorial to work with categories instead of pages. I have to admit I kind of learn this stuff as I go so not sure if I’m doing something wrong. I’m more familiar with html and css. I’ve placed the following code at the end of my functions.php page:


    class ext_breadcrumb_trail extends bcn_breadcrumb_trail
    {
    public $excluded_ids = array();
    function __construct($excluded_ids)
    {
    $this->excluded_ids = $excluded_ids;
    parent::__construct();
    }
    /**
    * category_parents
    *
    * A Breadcrumb Trail Filling Function
    *
    * This recursive functions fills the trail with breadcrumbs for parent categories.
    * @param (int) $id The id of the parent category.
    * @param (int) $frontpage The id of the front category.
    */
    function category_parents($id, $frontpage)
    {
    $parent = get_post($id);
    //Check if the current category should be excluded
    if(!in_array($id, $this->excluded_ids))
    {
    //Place the breadcrumb in the trail, uses the constructor
    $breadcrumb = $this->add(new bcn_breadcrumb(
    apply_filters('the_title', $parent->post_title),
    $this->opt['category_prefix'], $this->opt['category_suffix']));
    //Assign the anchor properties
    $breadcrumb->set_anchor($this->opt['category_anchor'],
    get_permalink($id));
    }
    //Make sure the id is valid
    if($parent->post_parent >= 0
    && $parent->post_parent != false
    && $id != $parent->post_parent
    && $frontpage != $parent->post_parent)
    {
    //If valid, recursively call this function
    $this->category_parents($parent->post_parent, $frontpage);
    }
    }
    }

    I’ve identified the category IDs with which I want to exclude, and put them in the calling code block example above. My question is, you state to: replace all instances of “bcn_breadcrumb_trail” with “ext_breadcrumb_trail” in the calling code. Where is the original calling code located? In the functions.php page, the only instance of this would be the class I just added. Where would I find the original calling code and would I place the calling code block with excluded categories in this page?

    • Here’s how I handled it:
      class ext_breadcrumb_trail extends bcn_breadcrumb_trail
      {
      public $excluded_ids = array();
      function __construct($excluded_ids)
      {
      $this->excluded_ids = $excluded_ids;
      parent::__construct();
      }
      /**
      * category_parents
      *
      * A Breadcrumb Trail Filling Function
      *
      * This recursive functions fills the trail with breadcrumbs for parent categories.
      * @param (int) $id The id of the parent category.
      */
      function term_parents($id, $taxonomy)
      {
      if(!in_array($id, $this->excluded_ids))
      {
      global $post;
      //Get the current category object, filter applied within this call
      $term = &get_term($id, $taxonomy);
      //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
      $breadcrumb = $this->add(new bcn_breadcrumb($term->name, $this->opt[$taxonomy . '_prefix'], $this->opt[$taxonomy . '_suffix']));
      //Figure out the anchor for the term
      $breadcrumb->set_anchor($this->opt[$taxonomy . '_anchor'], get_term_link($term, $taxonomy));
      //Make sure the id is valid, and that we won't end up spinning in a loop
      if($term->parent && $term->parent != $id)
      {
      //Figure out the rest of the term hiearchy via recursion
      $this->term_parents($term->parent, $taxonomy);
      }
      }
      }
      }

  7. Hey John, scratch the above comment. I’m close to getting this to work and hope you can help me on a couple final questions based on what I’ve done so far:

    Again, I’m looking to exclude categories vs pages. I took the code for “category_parents” from “breadcrumb_navxt_class.php” and substituted it in the example above. My functions.php file obviously contains developer functions within the tags.

    When adding the “ext_breadcrumb_trail” class to this page, would I add the modified class code above within the pre-existing tags, or rather something like this:


    <div class="ext_breadcrumb_trail">
    <?php
    class code
    ?>
    </div>

    …and put it below and outside the existing tag set?

    Lastly, when you state to: replace all instances of “bcn_breadcrumb_trail” with “ext_breadcrumb_trail” in the calling code with excluded IDs, would I just replace the basic usage div class code in my header.php file with the new one?

    Thanks John,

    Logan

    • Logan,

      When I said replace all instanced, what I meant is if you are already directly calling the bcn_breadcrumb_trail class, then all you have to do is a find/replace for bcn_breadcrumb_trail and replace with ext_breadcrumb_trail for the block of calling code. Since you were using the basic calling code that line does not apply to you. For calling the “new” ext_breadcrumb_trail class you’d use the last block of code in the tutorial instead of the bcn_display() function from the basic usage.

      -John Havlik

  8. Hi,

    When I use this code to exclude pades from breadcrumb trail, I lose ability to modify it in the settings panel. I can’t change home page title, trail always starts with Blog and not with Home Title I set in the settings panel.
    Am I missing something?

    • Jonas,

      It wasn’t explicitly mentioned here, but when you directly call the bcn_breadcrumb_trail class, or in this case ext_breadcrumb_trail class, the settings panel settings do not get applied. You must set the particular settings as you would in the “advanced usage” section in the Breadcrumb NavXT Documentation.

      -John Havlik

    • I mean, I know I can set those things manualy, but do I really have to make settings panel useless if i want to exclude pages?

      • Jonas,

        Well, you could do the following:

        $breadcrumb_trail->opt = get_option('bcn_options');

        Though, things may change with version 3.5/4.0 as the administrative interface is being rewritten.

        -John Havlik

  9. I’m absolutely clueless how to follow this..

    I don’t know where to start…I can’t just copy paste some code, edit the page IDs I don’t want to display and ‘voila’?

    forgive the ignorance…

    • Mike,

      Currently, the code above is FUBAR due to enabling the syntax highlighter. Give me a day or two and I’ll get it back to a normal state.

      -John Havlik

      • What’s the go with the fubar code?
        Will any future releases of NavXT have simple toggle on/off for pages to display the plugin?

        • Mike,

          I fixed the code that is in the article, it should be copy and paste now. At this time, I have no intent of integrating this as an option into Breadcrumb NavXT. There are more important things I need to add (support for custom post types), and with those there should not longer be a need for hidden posts/pages (IMHO there never was a really good reason).

          -John Havlik

  10. mtekk: Mike,I fixed the code that is in the article, it should be copy and paste now. At this time, I have no intent of integrating this as an option into Breadcrumb NavXT. There are more important things I need to add (support for custom post types), and with those there should not longer be a need for hidden posts/pages (IMHO there never was a really good reason).-John Havlik

    Hi, John:

    My custom posts (I’m using WP 3.0) aren’t showing up in the breadcrumb trail.

    Do you you know how to make them appear? Thank you for any help with this!

    Manon

    • Manon,

      You need to use the SVN trunk of Breadcrumb NavXT to get functioning support for custom post types. Let me know if you have any issues with the SVN trunk version.

      -John Havlik

  11. Hi. I can’t get it working. Here is the code I put in functions.php

    excluded_ids = $excluded_ids;
    parent::__construct();
    }
    /**
    * category_parents
    *
    * A Breadcrumb Trail Filling Function
    *
    * This recursive functions fills the trail with breadcrumbs for parent categories.
    * @param (int) $id The id of the parent category.
    * @param (int) $frontpage The id of the front category.
    */
    function category_parents($id, $frontpage) {
    $parent = get_post($id);
    //Check if the current category should be excluded
    if(!in_array($id, $this->excluded_ids)) {
    //Place the breadcrumb in the trail, uses the constructor
    $breadcrumb = $this->add(new bcn_breadcrumb(
    apply_filters(‘the_title’, $parent->post_title),
    $this->opt[‘category_prefix’], $this->opt[‘category_suffix’]));
    //Assign the anchor properties
    $breadcrumb->set_anchor($this->opt[‘category_anchor’],
    get_permalink($id));
    }
    //Make sure the id is valid
    if($parent->post_parent >= 0 && $parent->post_parent != false && $id != $parent->post_parent && $frontpage != $parent->post_parent) {
    //If valid, recursively call this function
    $this->category_parents($parent->post_parent, $frontpage);
    }
    }
    }
    ?>

    And this is the code I put in archive.php

    opt[‘separator’] = ‘ › ‘;
    $breadcrumb_trail->opt[‘home_title’] = ‘Home’;
    $breadcrumb_trail->opt[‘archive_category_prefix’] = false;
    $breadcrumb_trail->opt[‘archive_category_suffix’] = false;
    $breadcrumb_trail->opt[‘current_item_prefix’] = ”;
    $breadcrumb_trail->opt[‘current_item_suffix’] = ”;
    //Fill the breadcrumb trail
    $breadcrumb_trail->fill();
    //Display the trail
    $breadcrumb_trail->display();
    }
    ?>

    But the category is not excluded. Do I doing something wrong?

    Thanks in advance.

    • Matias,

      Well, the first problem is that this code needs to be within a class that extends bcn_breadcrumb_trail. Then you need to create an instance of that class and call the correct functions (see above for good examples).

      -John Havlik

      • Oh..sorry. I paste the code in my theme truncated. Here is the entire code:

        opt[‘separator’] = ‘ › ‘;
        $breadcrumb_trail->opt[‘home_title’] = ‘Home’;
        $breadcrumb_trail->opt[‘archive_category_prefix’] = false;
        $breadcrumb_trail->opt[‘archive_category_suffix’] = false;
        $breadcrumb_trail->opt[‘current_item_prefix’] = ”;
        $breadcrumb_trail->opt[‘current_item_suffix’] = ”;
        //Fill the breadcrumb trail
        $breadcrumb_trail->fill();
        //Display the trail
        $breadcrumb_trail->display();
        }
        ?>

        • Oppps…once again the code doesn’t show at all. Lets try again.

          if(class_exists(‘ext_breadcrumb_trail’))
          {
          //Make new instance of the ext_breadcrumb_trail object
          $breadcrumb_trail = new ext_breadcrumb_trail(array(3));
          //Setup options here if needed
          $breadcrumb_trail->opt[‘separator’] = ‘ › ‘;
          $breadcrumb_trail->opt[‘home_title’] = ‘Home’;
          $breadcrumb_trail->opt[‘archive_category_prefix’] = false;
          $breadcrumb_trail->opt[‘archive_category_suffix’] = false;
          $breadcrumb_trail->opt[‘current_item_prefix’] = ”;
          $breadcrumb_trail->opt[‘current_item_suffix’] = ”;
          //Fill the breadcrumb trail
          $breadcrumb_trail->fill();
          //Display the trail
          $breadcrumb_trail->display();
          }

          • Matias,

            Use the html code tags to get code to display correctly in comments (it won’t do odd truncation). Still, you need to have the functions in your first comment in an extending class of bcn_breadcrumb_trail (in this case ext_breadcrumb_trail). Once you have that, then the calling code you posted in your latest comment should work.

            -John Havlik

    • Yes, that is due to the addition of support for custom post types. The post and page code was modified to be more generic, and some functions were renamed.

      post_parents() replaces page_parents() is the major name change, but there were minor changes with in the function itself that you need to look out for when modifying the code in this post to work on 3.6 and newer. I’ll get to updating it eventually.

      -John Havlik

      • Hi, I’ve just upgraded to 3.6 and it has brought my site down. I am getting the following error ‘Fatal error: Class ‘bcn_breadcrumb_trail’ not found in /home/site106/public_html/wp-content/themes/bmlcreative/functions.php on line 115′. I am using the code above to exclude certain pages within the site.

        Everything was working perfectly before the update. I’ve tried deleting the new version of the plugin and copying the old files across from my local machine but it won’t work. Please can you advise – I’m desperate to get this sorted.

        • David,

          Did you do a deactivation/activation cycle after replacing the new files with the old ones? It sounds like a code caching issue.

          -John Havlik

  12. Hey John,

    I’m hoping to use your plugin for breadcrumbs on my website. We are looking to exclude certain categories from our breadcrumb trail because those categories are simply used for functionality with the site and the user should never actually be able to see them.

    If you have any guidelines to modifying your class in 3.6 to encompass this functionality I would greatly appreciate it. I am in a bit of a rush to get this done.

    Thanks so much for your help.

    • Seth,

      Is there a reason that you are not using custom taxonomies rather than hidden categories? Honestly, it will most likely be the simplest way to do what you want (and in the long run will be less of a headache).

      If you absolutely need to use categories for the “private”/hidden stuff, then at the moment I would recommend looking at the bcn_before_fill and bcn_after_fill action hooks (works just like other WordPress action hooks). The other method is to use OOP principles and extend bcn_breadcrumb_trail, overriding the term_parents function.

      -John Havlik

  13. mtekk,

    can you give me solution, which exclude some parent categories ?

    I’ve tryed the code above but it wont work with me.

  14. I’ve found a solution, it help but not so good as I want.

    I’ve edited breadcrumb_navxt_class.php at line 414:
    from
    //We want the first term hiearchy
    if($object->parent > 0)
    {
    $bcn_use_term = $key;
    //We found our first term hiearchy, can exit loop now
    break;
    }

    to:
    //We want the first term hiearchy
    if($object->parent > 0 && $object->parent != '286') // 286 - is excluded id
    {
    $bcn_use_term = $key;
    //We found our first term hiearchy, can exit loop now
    break;
    }

    Please help me.

  15. Hi,

    I’ve been using a customized breadcrumbs following this tutorial It had worked really well. But since the update to version 4.0.0 the function bcn_breadrumbs->set_anchor has vanished. Is there now another way to manipulate the breadcrumbs trail?

    • This guide was only valid for Breadcrumb NavXT 3.x. In 4.0 extensive changes to the settings, and some changes to the internal structure have made this guide invalid. There is probably a better way of doing this now, that doesn’t require directly accessing the class (a guide may be forthcoming, if I have time).

      -John Havlik

      • Thanks for this detailed tutorial, but i fear it is no longer relevant right?
        I am trying to hide the breadcrumb trail when there is only one item in it. i.e. when i am on a top level, on my site one example of that would be “Europe” no real need to have a breadcrumb on this page right? i am sure this is available somewhere and i am just missing it.

        http://www.HoneyTrek.com/category/europe/

        thanks guys,
        mike

        • Hi Mike,

          Yeah, this guide is obsolete. At the same time, for what you want to do, this guide was never applicable. Assuming the set of pages with short breadcrumb trails is small, the correct way is to just not render the breadcrumb trail on those pages. To do this, wrap the bcn_breadcrumb_display() call in an if statement that checks the appropriate WordPress Conditional Tag.

          -John Havlik

  16. Where do you add the last part:
    if(class_exists('ext_breadcrumb_trail'))
    {
    //Make new instance of the ext_breadcrumb_trail object
    $breadcrumb_trail = new ext_breadcrumb_trail(array(100,230,231));
    //Setup options here if needed
    //Fill the breadcrumb trail
    $breadcrumb_trail->fill();
    //Display the trail
    $breadcrumb_trail->display();
    }

    I have no call in my functions.php, I just add the breadcrumbs with:


    <?php if(function_exists('bcn_display'))
    {
    //bcn_display();
    }?>

    ???

    • As stated at the top of the article, this guide is no longer applicable for Breadcrumb NavXT 4.0 or newer. Instead, you will want to write a function that hooks into the bcn_after_fill action.

      -John Havlik

Comments are closed.