Breadcrumb Helper

This article is also available in the following languages:
By toxic_brain
If you are tired of setting up breadcrumbs for your screens, this helper is for you.
  • This line adds the current page to the breadcrumb list stored in session and returns the breadcrumb html.

View Template:


echo $crumb->getHtml('Postings') ;
  • second argument is used to instruct the helper to perform some pre-defined actions. Currently supported is 'reset'. It is used to clear the old stored list and start a new one. Normally, this option should be used when calling from the template to which the first link in the breadcrumb point to.

echo $crumb->getHtml('Postings', 'reset') ;
  • The third parameter is to handle browser's Back button clicks. For example, If we have a listing page 'Postings' which links to an Edit page and an Add page. Here, give the level something like 'Post'. So the Helper can identify the Add and Edit screens falls in the same level as Postings > Add and Postings > Edit. Otherwise it will build one as, Postings->Add->Edit if we clicked on the Edit link followed by "Back" button then the Add link.

echo $crumb->getHtml('Postings', null, 'Post' ) ;

If you are not sure what to use for the third parameter, use 'auto' and let the Breadcrumb helper to analyse it for you.


echo $crumb->getHtml('Postings', null, 'auto' ) ; 

Create this file app/views/helpers/crumb.php:

Helper Class:

<?php 
class CrumbHelper extends Helper
{
var 
$link_class    'crumb_link'    ;    // css class for anchor tags.
var $span_class    'crumb_span'    ;    // css class for the span element .(last label).
var $separator    ' > '            ;    // separator between links.
var $protocol    'http'            ;
var 
$helpers     = Array("Session");

function 
addThisPage($title null$what_to_do null $level null )    // add the calling page
{
    
define('THIS_URL' $this->protocol.  '://' $_SERVER['HTTP_HOST'] .  $_SERVER['REQUEST_URI']) ;

    
$controller       =    $this->params['controller']    ;
    
$action            =    $this->params['action']        ;

    if (
is_null($title)) {
        
$title Inflector::humanize($controller);
    }

    if (
$what_to_do == 'reset' )    { // add this argument if it comes from menu.
        
$this->Session->del('crumb_links') ;
        
$this->Session->del('crumb_titles') ;
        
$this->Session->del('crumb_levels') ;
    }
    if ( !isset(
$_SESSION['crumb_links'])) {
        
$_SESSION['crumb_links'] = array() ;
        
$_SESSION['crumb_titles'] = array() ;
        
$_SESSION['crumb_levels'] = array() ;
    }
    
$arr_links    $this->Session->read('crumb_links')    ;
    
$arr_titles    $this->Session->read('crumb_titles');
    
$arr_levels    $this->Session->read('crumb_levels');

    if (
is_null($level) AND $this->params['action'] != 'index' && $level != 'auto') {
        
$level $controller ;
    }
    if ( 
$level == 'unique'){
        
$level $controller '_' $action ;
    }

    
// check that same level exists. if yes strip all after it.
    
if ( is_array($arr_levels)) {
        
$level_found_at    =    array_search($level$arr_levels );
    }
    if (
is_numeric($level_found_at)) {
        
$arr_links    $this->__stripAfter($arr_links    $level_found_at  )        ;                // Delete items after current
        
$arr_titles    $this->__stripAfter($arr_titles    $level_found_at  )        ;                // Delete items after current
        
$arr_levels    $this->__stripAfter($arr_levels    $level_found_at  )        ;                // Delete items after current
        // reindex
        
unset($arr_links[$level_found_at] )    ;
        unset(
$arr_titles[$level_found_at] );
        unset(
$arr_levels[$level_found_at] );
        
$arr_links    array_values$arr_links )     ;
        
$arr_titles    array_values$arr_titles )     ;
        
$arr_levels    array_values$arr_levels )     ;
    }
    
// check last item is current page. if not, add, else do nothing.
    
if ( is_array($arr_titles)) {
        
$found_at    =    array_search($title$arr_titles);
    }
    if ( 
is_numeric($found_at)) {    //            ;    // already in the link, don't add
        
$arr_links    $this->__stripAfter($arr_links    $found_at  )    ;                // Delete items after current
        
$arr_titles    $this->__stripAfter($arr_titles    $found_at  )    ;                // Delete items after current
        
$arr_links[count($arr_links) - 1]    =     THIS_URL            ;
    } else { 
// not in list, add
        
$arr_links[]    =     THIS_URL;
        
$arr_titles[]    =    $title    ;
        
$arr_levels[]    =    $level    ;
    }

    
//write back to session
    
$_SESSION['crumb_links'] = $arr_links ;
    
$_SESSION['crumb_titles'] = $arr_titles ;
    
$_SESSION['crumb_levels'] = $arr_levels ;

}

/**
 * Add called page to the Bredcrumb session array and returns the new breadcrumb string.
 * @param string $title        : Title for the href tag.
 * @param string $action     : predefined actions, now supports 'reset'.
 * @param string $level        : Page level. Calling controller name by default.
 */
function getHtml($title null$what_to_do=null$level null)
{
    
$this->addThisPage($title$what_to_do$level)    ;

    
$arr_links    $this->Session->read('crumb_links') ;
    
$arr_titles    $this->Session->read('crumb_titles') ;
    
$last_index    count($arr_titles) - 1        ;
    
$string        '' ;
    for (
$i 0  $i <= $last_index  $i++) {
        
$title    =    $arr_titles[$i]    ;
        
$link    =    $arr_links[$i]    ;
        if (
$i $last_index) { // no need to build link for last item
            
$link sprintf('<a href="%s" class="%s">%s</a> %s '$link$this->link_class$title$this->separator)        ;
        } else {
            
$link sprintf("<span class='%s'>%s</span>"$this->span_class$title )                    ;     //last text, ie current page without link
        
}
        
$string    .=  $link                            ;
    }
    return 
$string;
}


 function 
__stripAfter($arr$after)
{
    
$count count($arr)    ;
    for (
$i $after $i $count $i++ ) {
        unset(
$arr[$i])    ;
    }
    return 
$arr ;
}
}
?>


Sample Code

app/contollers/wizards_controller.php

Controller Class:

<?php 
class WizardsController extends AppController {

    var 
$helpers = array('Html''Crumb');
    var 
$uses     = array() ;

    public function 
index(){
    }
    public function 
one(){
    }
    public function 
two(){
    }
    public function 
three(){
    }
}
?>

app/views/wizards/index.ctp( or .thtml if you have old version of
cake)

View Template:


<?
echo $crumb->getHtml('Home Page', 'reset' ) ;
echo '<br /><br />' ;
echo $html->link('One', 'one') ;
?>
app/views/wizards/one.ctp

View Template:


<?
echo $crumb->getHtml('First Page', null, 'auto' ) ;
echo '<br /><br />' ;
echo $html->link('Two', 'two') ;
?>

app/views/wizards/two.ctp

View Template:


<?
echo $crumb->getHtml('Second Page' , null, 'auto') ;
echo '<br /><br />' ;
echo $html->link('Three', 'three') ;
?>

app/views/wizards/three.ctp

View Template:


<?
echo $crumb->getHtml('Third Page' , null, 'auto') ;
?>

Comments

  • Posted 12/01/10 06:35:07 PM
    I do appreciate your work, but there is something that frustrate me, when I have a controller like '/bookings', every page of its actions will point to a named 'Home Page' to '/bookings', that's a little bit odd.
    So my suggestion is that use the name of the controller to replace the 'Home Page'.
    Hope it is ok to say so.
  • Posted 08/14/10 05:37:16 AM
    Works great...although your 'auto' analyse does not work in my app within static pages (pages_controller), but setting the parameter correctly helps. Thanks for the great helper!
  • Posted 07/20/10 04:01:13 PM
    thank you nice post.
  • Posted 07/08/10 10:59:38 AM
    using time() as the 3rd param also seems to help
  • Posted 07/08/10 10:50:54 AM
    I've been struggling to get this helper working. It always only showed one Crumb on the page and not the entire trail. Using "auto" as the third parameter didn't work. My problem was that I navigate in one controller and then it doens't work. The solution, make the first and third parameters the same or use something like $this->passedArgs[0] as the third parameter.
  • Posted 06/02/10 07:44:01 AM
    works fine. thanks
  • Posted 02/21/10 11:55:49 PM
    @jitendra:
    You would need to do in the Home page as

    echo $crumb->getHtml('Home');
    and in the user page

    echo $crumb->getHtml('User');

    or did you already give a try?
    • Posted 02/22/10 01:17:29 AM
      @jitendra:
      You would need to do in the Home page as

      echo $crumb->getHtml('Home');
      and in the user page

      echo $crumb->getHtml('User');

      or did you already give a try?

      i tried this also but the same output....... plz guys help me out yaar...
  • Posted 02/20/10 05:36:22 AM
    I have the code in and I am not getting any errors.
    I get back the single breadcrumb on all my pages. I have the line

    echo $crumb->getHtml('Mypage name');
    in each view file.

    i want home > user > userprofile > album
  • Posted 12/19/09 02:09:41 PM
    I have the code in and I am not getting any errors.

    I get back the single breadcrumb on all my pages. I have the line

    echo $crumb->getHtml('Mypage name');

    No matter what I do the session array is cleaned out at each page and only one crumb is listed.

    Am I missing something?
    • Posted 12/29/09 01:08:37 AM
      I have the code in and I am not getting any errors.

      I get back the single breadcrumb on all my pages. I have the line

      echo $crumb->getHtml('Mypage name');

      No matter what I do the session array is cleaned out at each page and only one crumb is listed.

      Am I missing something?

      Make sure you are passing unique page names from different pages.
      eg: echo $crumb->getHtml('Mypage name one');
      echo $crumb->getHtml('Mypage name two');
      Let me know.
      • Posted 01/13/10 01:10:53 AM
        I managed to get it to work. I found that

        $crumb->getHtml($this->passedArgs[0], null, 'auto') 
        doesn't work, but

        $crumb->getHtml($this->passedArgs[0]);
        does work.

        May I suggest that you update the helper's getHtml function to take only $this as a parameter.
        In the helper $title will now be a view object. Perhaps rename this to $view. Then instead of using the passed title, you use the view name ($view->getPassedArgs[0]) as the key and the page title ($view->pageTitle) as the text that is output. That way the output will look better and you won't have to uniquely name each page.
  • Posted 08/05/09 04:25:56 PM
    Hi,

    I have followed the above instructions but I am getting this error:

    Notice (8): Undefined variable: crumb [APP\views\groups\admin_index.ctp, line 9]
    echo $crumb->getHtml('Postings', null, 'auto' ) ;?>
    Fatal error: Call to a member function getHtml() on a non-object in C:\xampp\htdocs\video\app\views\groups\admin_index.ctp on line 9

    Could you please let me know what's the wrong I am doing..

    Thanks,
    Raj
    • Posted 08/06/09 01:00:58 AM
      It looks like the helper didn't get loaded. Make sure

       var $helpers = array(,..,..,'Crumb'); 
      is there.

  • Posted 06/06/09 08:56:05 AM
    Could this helper be made to work with multiple subdomains? At present, the plugin immediately purges the list if you go from example.com to subd.example.com. Also, it would be nice to be able to add a page to the list without displaying it. I'm thinking in particular for home pages, which you'd want your audience to be able to navigate back to, but which you wouldn't want displaying "home."

    Thanks!
    • Posted 06/26/09 03:31:27 AM
      Could this helper be made to work with multiple subdomains? At present, the plugin immediately purges the list if you go from example.com to subd.example.com.

      add line in the helper file.

      <?php 
      ini_set
      ('session.cookie_domain',substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));

      class 
      CrumbHelper extends Helper
      {
      var 
      $link_class    'crumb_link'    ;    // css class for anchor tags.
      var $span_class    'crumb_span'    ;    // css class for the span 
      .....
      .....


      I couldn't able to setup sub domain in my desktop, so not able to test the new code, let me know if this code doenst make what is suppose to.
  • Posted 03/29/09 11:02:25 AM
    This is a great helper, thanks.

    A little more explanation of what is happening in the third parameter would be helpful - I don't understand exactly when it is to my benefit to put in a string versus leaving it as auto - though I was able to get it to work correctly with a minimum of trial and error around that third parameter.

    All in all really useful. thanks.
  • Posted 08/10/08 03:12:15 AM
    Code shown abowe doesn't work.
    You use $action variable in addThisPage() mothod in two separate context.

    One is coltroller action, other action passed in as a parameter ('reset' for exmple). To fix this, make the following changes.

    Replace line:

    function addThisPage($title = null, $action = null , $level = null ) {
    with:

    function addThisPage($title = null, $act = null , $level = null ) {

    and replace line:

    if ($action == 'reset' )    {
    with line:

    if ($act == 'reset' )    {
  • Posted 07/25/08 05:15:51 AM
    the steps are simple.
    1. Download crumb.php and copy to ur helpre folder(probably app/views/helpers/).
    2. Add var $helpers = array(...,...,'Html', 'Crumb'); to the controllers of views which u are planning to show breadcrumbs. or even app_controller itself.
    3. Out the line echo $crumb->getHtml('My Page') ; in ur views.
    4. Thats it!.

    u can PM me on anoopchat@yahoo.com if u still have questions.
  • Posted 07/25/08 04:37:05 AM
    Hi
    Can please explain it step by step how to use.
    its very urgent.

    Thanks
    Binay
  • Posted 01/24/08 08:07:27 AM
    How can i add Links there? I dont understand this System, sorry

    Can anyone explain me more in detail? Iam very new at Cake
  • Posted 12/07/07 05:33:02 AM
    Working sample pages has been added. Thanks jigga smoka.
  • Posted 12/04/07 03:15:46 PM
    How about a working example with a sample page?

    Thanks!
  • Posted 11/30/07 01:50:44 AM
    hello guys, this is my first submission to the Bakery. I would like to know your valuable comments. :)

Comments are closed for articles over a year old