While making an ecommerce store I ran into the issue of displaying a category breadcrumb. Usually this is easy as I always recommend keeping the numbers of categories and sub categories to a maximum of 1 level deep. E.g. Tshirts > Red tshirts. For this store, due to the sheer number of products the owner wanted to add up to seven category levels. While there are many tutorials on this floating about, they all seem tocus on displaying the whole tree – very useful for a sitemap page, but not a breadcrumb navigation. While it would have been possible to hard code several if statements into the category listing page, this seemed a bit messey and would cause problems if an eighth level was added.
For the breadcrumb naviagtion I needed a function to displaying the path to a given category ID, sometimes refered to as a single branch or node. I was using a simple parent child database table structure:
While the latter may seem fairly trival I really couldn’t get my head around the problem. After a bit of Googling, I found a function that was a good starting point so adapted it to fit my problem (the function is part of a categoru class):
function getCategoryTreeIDs($catID) { $row = DB::getInstance()->query("SELECT parent FROM categories WHERE ID = '$catID'")->fetch(); $path = array(); if (!$row['parent'] == '') { $path[] = $row['parent']; $path = array_merge($this->getCategoryTreeIDs($row['parent']), $path); } return $path; }
The function simply returns an array of category IDs. E.g 20, 28. So from the array I’d know that the tree would go as Home > Cat ID 20 > Cat ID 28.
Displaying the Breadcrumb Navigation
To display the actual breadcrumb I simply added the following method, that loops through the array of ID we just generated. The getNameLink method simply generates an SEO feindly website URL for the category, inside the <a> tag.
function showCatBreadCrumb($catID) { $array = $this->getCategoryTreeIDs($catID); $numItems = count($array); for ($i = 0; $i<=$numItems-1; $i++) { echo $this->getNameLink($array[$i]) . ' » '; } }
The result is a nicely formatted breadcrumb (to use our tshiorts example again):
Home &rquao; Clothes &rquao; tshirts &rquao; Mens &rquao; Red tshirts &rquao; Offensive &rquao;
A recursive function inside a loop, are you insane?
Some of you may have noticed that the function used to generate the category IDs is called recursively. This generally considered bad practice, for large data sets due to performance issues. However, for the current use this isn’t an issue. I know for a fact that client won’t be adding categories more than several levels deep, so performance really isn’t an issue in my eyes here. Maybe if we had hundreds of categories, but for several it’s really a non issue in my opinion.
getCategoryTreeIDs
Thanks it works I only have to change a few thinks but it’s great!
how can i use this on a php page? when i do showCatBreadCrumb($cat); i get this error: Fatal error: Using $this when not in object context in C:\AppServ\www\s\inc\position.php on line 73
That’s because the mthods are intended to be used as part of a class and not as standalone functions – as $this-> implies. I’d highly reocmmend you go have a read of some basic php tutorials at w3schools.com.
Hi, great tutorial. I did a little tweak, and it’s seem didn’t work.
Here is the code.
function getCategoryTreeIDs($qs_type_id) {
$crumbsql = “SELECT parent_id FROM lists WHERE id=$qs_type_id”;
$crumbresult = tep_db_query($crumbsql);
$crumbrow = tep_db_fetch_array($crumbresult);
$path = array();
if (!$crumbrow[‘parent_id’] == ”) {
$path[] = $crumbrow[‘parent_id’];
$path = array_merge($this->getCategoryTreeIDs($crumbrow[‘parent_id’]), $path);
}
return $path;
}
function showCatBreadCrumb($qs_type_id) {
$array = $this->getCategoryTreeIDs($qs_type_id);
$numItems = count($array);
for ($i = 0; $igetNameLink($array[$i]) . ‘ » ‘;
}
}
Can you tell me, what’s wrong with the code. Because when i clicked on categories, the breadcrumb didn’t show.
Many thanks.
Just from a quick glance, your loop in your showcatbtreadcrumb function looks off. $igetNameLink should be a condition E.g. $i<10 ....
Hi, great tutorial. I did a little tweak, and it’s seem didn’t work.
Here is the code.
function getCategoryTreeIDs($cati) {
$row1 = mysql_query(“SELECT parent_category_id FROM catagory WHERE catid=’$cati'”);
$row = mysql_fetch_array($row1);
$path = array();
if (!$row[‘parent_category_id’] == ”) {
$path[] = $row[‘parent_category_id’];
$path = array_merge($this->getCategoryTreeIDs($row[‘parent_category_id’]), $path);
}
return $path;
}
function showCatBreadCrumb($cati) {
$array = $this->getCategoryTreeIDs($cati);
$numItems = count($array);
for ($i = 0; $igetNameLink($array[$i]) . ‘ » ‘;
}
}
Where is the
getNameLink
function?. Can you please write it?. Thanks in advance before…Ah, it was (very, very, very old code). I have removed a function that did return an seo link and a simple hyperlink based upon the site’s base url and runs the category through a small function generate an seo friendly url slug). You could change this function to just return the url if required, as I have done below.
private function getNameLink($catID) {
$catID = (int) $catID;
$check = DB::getInstance()->query("SELECT ID, Name FROM categories WHERE ID = '$catID' LIMIT 1")->fetch();
return "/category/" . $check['ID'] . "/" . $check['Name'] . "/"; // TODO: slugify the category name
}