Page 1 of 1

Help reg. Breadcrumbs

Posted: Fri Sep 12, 2008 2:14 am
by Tokci
I'm making an application where I've to display breadcrumbs for all pages. Those are not based on directory structure and some customization is required.

I'll give an example:

my 1st page shows list of administrators

Code: Select all

Breadcrumb : Home
Once you select an administrator

Code: Select all

Breadcrum : Home > Administrator Name
Now this page will contain list of users under that admin...and other links like change password, edit details.

Since change password/edit details are under this admin, if we visit these pages the breadcrumb will not change, but when we select a user (from the list), it changes to

Code: Select all

Breadcrumb : Home > Adminstrator Name > User Name
I'm not sure if I'm able to convey the logic correctly.

I don't know I should do it using a database table or session. Database table might not be helpful because I need to store the full breadcrumb path for each page, along with the parameters (like Administrator Name will have adminId in the link).

I've ran of ideas and am planning to hardcode the breadcrum for each page...unless someone can drop in some idea.

Thnx.

Re: Help reg. Breadcrumbs

Posted: Fri Sep 12, 2008 2:48 am
by onion2k
Your breadcrumb trail is really just a reflection of your menu or navigation structure. If you hard code the menu of your site then the chances are you're doing to have to hard code the breadcumbs too, at least in part. Personally, my sites all have menus that are stored in the database (because that way I can give each user a custom menu based on their permissions/user level) so my sites breadcrumbs are all generated in the same way ... I know what breadcrumbs there should be just by selecting the tree path from the database.

Re: Help reg. Breadcrumbs

Posted: Fri Sep 12, 2008 5:20 am
by Stryks
I was working with a site a while back that had an odd menu setup where you could get to the same place more than one way, so I had to devise something that would keep a track of things for me.

The following class is what I came up with. It may not be the most elegant solution, but it should get the job done.

Code: Select all

<?php
 
class breadcrumb {
    // Class Variables
    private $intro = "You are here: ";      // Configuration: Breadcrumb lead-in text
    private $spacer = " > ";                // Configuration: Breadcrumb delimiter
    private $base_link = "index.php";       // Configuration: Base crumb URL    
    private $base_text = "Home";            // Configuration: Base crumb text
    
    public $output;                         // Holds breadcrumb output string
    public $this_page_name;                 // Holds the current levels text - for headings or whatever
    public $this_page_link;                 // Holds the current levels url - for redirects to the same page - etc
    public $back_link;                          // Holds the url for a link back one level
    
    public function __construct($base_link = "index.php", $base_text = "Home") {
        if(!isset($_SESSION['BC_NAV'])) $_SESSION['BC_NAV'][$base_text] = $base_link;
    }
    
    public function add_level($new_link, $new_text, $parent_link = false) {
        if(!isset($_SESSION['BC_NAV'][$new_text])) {
            // Add a new child to the breadcrumb tree
            $_SESSION['BC_NAV'][$new_text] = $new_link;     
        } else {
            // Clip any items after the current one
            while(end($_SESSION['BC_NAV']) != $new_link) array_pop($_SESSION['BC_NAV']);
        }
        // If $parent_link is set, make sure the new level is a direct descendant or shortcurcuit to base crumb 
        if($parent_link) {
            $parent_found = false;
            foreach($_SESSION['BC_NAV'] as $crumb_text=>$crumb_link) {
                if($parent_found) { if($crumb_link != $new_link) unset($_SESSION['BC_NAV'][$crumb_text]); }
                if($crumb_link == $parent_link) $parent_found = true;
            }
        }
        $this->generate();
    }
    
    private function generate() {
        $final_element = end($_SESSION['BC_NAV']);
        foreach($_SESSION['BC_NAV'] as $crumb_text=>$crumb_link) {
            if($crumb_link==$final_element) {
                $new_bc[] = "<em>$crumb_text</em>";
                $this->this_page_name = $crumb_text;
                $this->this_page_link = $crumb_link;
            } else {
                $this->back_link = $crumb_link;
                $new_bc[] = "<a href=\"$crumb_link\">$crumb_text</a>";
            }
        } 
        $this->output = $this->intro . implode($this->spacer, $new_bc);
    }
}
?>
Now to be honest with you, I don't know if this is the latest revision or one of the versions on the way to getting it the way I wanted it, but after a brief scan it seems like it should be OK. Nothing jumps out at me.

Anyhow, you'd use it like this.

Code: Select all

// Start breadcrumb tracking
require_once(PATH_CLASS . "class_breadcrumb.php");
$bread = new breadcrumb();
 
// Add breadcrumb level
$bread->add_level("index.php", "Home");
 
// Display page details
<div id="page-name"><?php echo $bread->this_page_name; ?></div>
<div id="page-bread"><?php echo $bread->output; ?></div>
 
You don't have to use the div's for display purposes of course ... it's just how I did it so that I could apply the styles as I liked.

So basically you just the above on each page, except change the $bread->add_level() accordingly. E.g ...

Code: Select all

$bread->add_level("signup.php", "Join Now");
Anyhow, they should keep stacking on top of each other until you start moving back into previous pages, were it should just clip the breadcrumb down accordingly.

As I have said .. it may or may not work 100% ... but it should help out if you don't have any other logic structure to tie the breadcrumbs to.

Cheers

Re: Help reg. Breadcrumbs

Posted: Fri Sep 12, 2008 5:23 am
by Stryks
Oh yeah ... you need to have sessions running of course.

Code: Select all

// Top of page
session_start();

Re: Help reg. Breadcrumbs

Posted: Fri Sep 12, 2008 5:47 am
by onion2k
The problem with using a session based approach is what happens if someone links directly to a product? If I send you an email with "Check out this cool widget - http://www.domain.com/products/1/cool-widget", what would the breadcrumbs on the resulting page be?

Re: Help reg. Breadcrumbs

Posted: Fri Sep 12, 2008 5:55 am
by Stryks
Ah well .. then you've either got to manually populate the previous pages if the correct chain doesn't exist, or use a different method.

In the case of the site that this was made for, there was no such problem.

Anyhow, worst case scenario, they get a breadcrumb leading them home only. it could be worse. (although it does kind of negate the whole breadcrumb idea)

But yeah, for a site listing products in a catalog environment, you'd like to think that there would be a better structure to tie your navigation no ... such as the database method you mentioned.

But given that I don't know what the exact environment the OP is after, I just thought I'd throw it out there.

:)

Re: Help reg. Breadcrumbs

Posted: Fri Sep 12, 2008 8:33 am
by Tokci
hey thnx for ur replys...I'm using db for navigation purpose but links are different in navigation and breadcrumbs...lemme explain it a little more...as in the example I gave suppose I select an admin from the list...breadcrumb becomes:

Home > Admin Name

and I'm given 2 navigation options (these are basically actions I can take):

Edit Details
Change Password

which takes the use to the respective pages...In both these pages breadcrumb remain as

Home > Admin Name

as these option (or area) comes under that particular admin.

I've made tables for navigation where I'm definind which link to put in which page and its working perfect.

Maybe I'm in trying to complicate things for breadcrumbs or I'm not able to see the obvious...

Stryks, I'll look into the code u've given and get back to u...may this will solve my prob. Thnx again.

Re: Help reg. Breadcrumbs

Posted: Mon Sep 15, 2008 3:51 am
by Tokci
Stryks wrote:I was working with a site a while back that had an odd menu setup where you could get to the same place more than one way, so I had to devise something that would keep a track of things for me.

The following class is what I came up with. It may not be the most elegant solution, but it should get the job done.

Code: Select all

<?php
 
class breadcrumb {
    // Class Variables
    private $intro = "You are here: ";      // Configuration: Breadcrumb lead-in text
    private $spacer = " > ";                // Configuration: Breadcrumb delimiter
    private $base_link = "index.php";       // Configuration: Base crumb URL    
    private $base_text = "Home";            // Configuration: Base crumb text
    
    public $output;                         // Holds breadcrumb output string
    public $this_page_name;                 // Holds the current levels text - for headings or whatever
    public $this_page_link;                 // Holds the current levels url - for redirects to the same page - etc
    public $back_link;                          // Holds the url for a link back one level
    
    public function __construct($base_link = "index.php", $base_text = "Home") {
        if(!isset($_SESSION['BC_NAV'])) $_SESSION['BC_NAV'][$base_text] = $base_link;
    }
    
    public function add_level($new_link, $new_text, $parent_link = false) {
        if(!isset($_SESSION['BC_NAV'][$new_text])) {
            // Add a new child to the breadcrumb tree
            $_SESSION['BC_NAV'][$new_text] = $new_link;     
        } else {
            // Clip any items after the current one
            while(end($_SESSION['BC_NAV']) != $new_link) array_pop($_SESSION['BC_NAV']);
        }
        // If $parent_link is set, make sure the new level is a direct descendant or shortcurcuit to base crumb 
        if($parent_link) {
            $parent_found = false;
            foreach($_SESSION['BC_NAV'] as $crumb_text=>$crumb_link) {
                if($parent_found) { if($crumb_link != $new_link) unset($_SESSION['BC_NAV'][$crumb_text]); }
                if($crumb_link == $parent_link) $parent_found = true;
            }
        }
        $this->generate();
    }
    
    private function generate() {
        $final_element = end($_SESSION['BC_NAV']);
        foreach($_SESSION['BC_NAV'] as $crumb_text=>$crumb_link) {
            if($crumb_link==$final_element) {
                $new_bc[] = "<em>$crumb_text</em>";
                $this->this_page_name = $crumb_text;
                $this->this_page_link = $crumb_link;
            } else {
                $this->back_link = $crumb_link;
                $new_bc[] = "<a href=\"$crumb_link\">$crumb_text</a>";
            }
        } 
        $this->output = $this->intro . implode($this->spacer, $new_bc);
    }
}
?>
Now to be honest with you, I don't know if this is the latest revision or one of the versions on the way to getting it the way I wanted it, but after a brief scan it seems like it should be OK. Nothing jumps out at me.

Anyhow, you'd use it like this.

Code: Select all

// Start breadcrumb tracking
require_once(PATH_CLASS . "class_breadcrumb.php");
$bread = new breadcrumb();
 
// Add breadcrumb level
$bread->add_level("index.php", "Home");
 
// Display page details
<div id="page-name"><?php echo $bread->this_page_name; ?></div>
<div id="page-bread"><?php echo $bread->output; ?></div>
 
You don't have to use the div's for display purposes of course ... it's just how I did it so that I could apply the styles as I liked.

So basically you just the above on each page, except change the $bread->add_level() accordingly. E.g ...

Code: Select all

$bread->add_level("signup.php", "Join Now");
Anyhow, they should keep stacking on top of each other until you start moving back into previous pages, were it should just clip the breadcrumb down accordingly.

As I have said .. it may or may not work 100% ... but it should help out if you don't have any other logic structure to tie the breadcrumbs to.

Cheers

Stryks, Your code helped a lot...have made minor changes here and there...Thnx again.