You are here:  » Category Hierarchy in breadcrumbs and normalise


Category Hierarchy in breadcrumbs and normalise

Submitted by sirmanu on Tue, 2017-09-12 14:32 in

Hi David. First of all, sorry if it has been already posted. I have not found any topic about this.

1 ) Is it possible to show in the breadcumbs of a product page (products.php) the categories where a product belongs? In fact, is the same than the code under categories.php.

For example, for Samsung Galaxy A5.
Rather than just "Home/ Samsung Galaxy A5", I want "Home/ Electronics / Communicatinos / Smartphones"

Also, how can I insert the json for schema?
http://schema.org/BreadcrumbList

2) How can I tapestry_normalise my Category Hierarchy. I mean, my names are okey, but I want that the URLs are shown after pass with normalisation.
Example in Spanish:

Inicio/Automóvil should be showed, but in URL,you must have example.com/cat/automovil
(my normalise lower and remove accents)

Thanks!

Submitted by support on Wed, 2017-09-13 08:49

Hi,

To include category hierarchy in product page breadcrumbs, edit products.php and look for the following code at line 66:

      $banner["breadcrumbs"] = array();

...and REPLACE with:

      $banner["breadcrumbs"] = array();
      if ($id = $product["products"][0]["categoryid"])
      {
        $categories = array();
        do {
          $sql = "SELECT name,parent FROM `".$config_databaseTablePrefix."categories_hierarchy` WHERE id = '".$id."'";
          database_querySelect($sql,$rows);
          array_unshift($categories,$rows[0]["name"]);
        } while($id = $rows[0]["parent"]);
        $href = tapestry_indexHREF("category");
        foreach($categories as $category)
        {
          $href .= tapestry_hyphenate($category)."/";
          $banner["breadcrumbs"][] = array("title"=>$category,"href"=>$href);
        }
      }

For schema;
http://schema.org/BreadcrumbList

Edit html/banner.php and look for the following code at line 5:

  <ul class='breadcrumbs'>

...and REPLACE with:

  <ul class='breadcrumbs' <?php print (isset($banner["breadcrumbs"])?"itemscope itemtype='http://schema.org/BreadcrumbList'":""); ?>>

And then look for the following code at line 7:

  <li><a href='<?php print $config_baseHREF?>'>Home</a></li>

...and REPLACE with:

  <?php if (isset($banner["breadcrumbs"])): ?>
    <li itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'>
      <a itemprop='item' href='<?php print $config_baseHREF?>'><span itemprop='name'>Home</span></a>
      <meta itemprop='position' content='1' />
    </li>
  <?php else: ?>
    <li><a href='<?php print $config_baseHREF?>'>Home</a></li>
  <?php endif; ?>

And finally the following code at line 20:

  print "<li".($i==$c?" class='current'":"")."><a href='".$breadcrumb["href"]."'>".$breadcrumb["title"]."</a></li>";

...and REPLACE with:

  print "<li".($i==$c?" class='current'":"")." itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'>";
  print "<a itemprop='item' href='".$breadcrumb["href"]."'><span itemprop='name'>".$breadcrumb["title"]."</span></a>";
  print "<meta itemprop='position' content='".($i+1)."' />";
  print "</li>";

Regarding normalisation of category breadcrumb names, did you add the code to translate accented vowels since creating the hierarchy? I ask because category hierarchy names are normalised when added - check admin/categories_hierarchy.php at line 43 where you will see the call to tapestry_normalise() as part of the INSERT query. Let me know if that's the case, and I'll look at how best to hold both versions...

Cheers,
David.
--
PriceTapestry.com

Submitted by sirmanu on Wed, 2017-09-13 13:55

Awesome!

I only added the check for category hierarchy.

I just remembered that you sent me a modification version with expand / collapsible top level categories and that version it does not include normalise. However, it doesn't matter.

As for MySQL and my codification "Automóvil" is the same as "automovil", notice how I am doing the href (my tapestry_normalise lower and remove accents as described in other thread)

Finally, could you point me which lines I have to modify in categories.php to have href like this?
Regards

      if ($config_useCategoryHierarchy && $id = $product["products"][0]["categoryid"])
      {
        $categories = array();
        do {
          $sql = "SELECT name,parent FROM `".$config_databaseTablePrefix."categories_hierarchy` WHERE id = '".$id."'";
          database_querySelect($sql,$rows);
          array_unshift($categories,$rows[0]["name"]);
        } while($id = $rows[0]["parent"]);
        $href = tapestry_indexHREF("category");
        foreach($categories as $category)
        {
          $href .= tapestry_hyphenate(tapestry_normalise($category))."/";
          $banner["breadcrumbs"][] = array("title"=>$category,"href"=>$href);
        }
      }

Submitted by sirmanu on Wed, 2017-09-13 14:43

I think I have it
In tapestry_indexHREF, I have added normalise:

      if ($config_useRewrite)
      {
        $href .= tapestry_hyphenate(tapestry_normalise($entry,"\/"))."/";
      }

Is this correct?

Submitted by support on Wed, 2017-09-13 14:47

That's correct, and will cover everywhere a link to a category by path is generated, not just in categories.php.

Cheers,
David.
--
PriceTapestry.com

Submitted by sirmanu on Fri, 2017-09-15 16:30

Hi again! I have noticed that I will have minor SEO problems.
The thing is that my breadcrumbs have a large URL:
Example: example.com/cat/electronics/communications/smartphones

As I have unique names in pt_categories_hierarchy, it would be feasible to return has href in breadcrumbs just that node?

In the previous URL, each breadcrumb would point to

example.com/cat/electronics
example.com/cat/communications
example.com/cat/smartphones

Submitted by support on Sat, 2017-09-16 08:50

Hi,

Just to clarify, did you just want to be able to have shorter URLs in the breadcrumbs, so in other words

example.com/cat/smartphones/

...would redirect (301 Moved Permanently) to

example.com/cat/electronics/communications/smartphones/

Or, did you want to change the category hierarchy URL structure completely, so that you only have /cat/single-name/ URLs, and on for example

example.com/cat/electronics/

...the link for Communications would go to

example.com/cat/communications/

Cheers,
David.
--
PriceTapestry.com

Submitted by sirmanu on Sat, 2017-09-16 09:35

Ah sorry, maybe I didn't explain well.

Yes, I want to change how the href are generated, or at least, having the choice to select which structure will be working in order to not modify functions en tapestry.php (just adding a new one).

For example, maybe a new line en .htacess with example.com/subcat/communications could be done?

Submitted by support on Sat, 2017-09-16 10:10

Hi,

You can support this entirely within categories.php giving the option to use either (provided of course that all names in the hierarchy are unique). To give this a go, look for the following code at line 8:

    $banner["breadcrumbs"] = array();

...and REPLACE with:

    if (strpos($path,"/")==FALSE)
    {
      $sql = "SELECT * FROM `".$config_databaseTablePrefix."categories_hierarchy` WHERE name='".database_safe($path)."'";
      if (database_querySelect($sql,$rows))
      {
        $id = $rows[0]["id"];
        $categories = array();
        do {
          $sql = "SELECT name,parent FROM `".$config_databaseTablePrefix."categories_hierarchy` WHERE id = '".$id."'";
          database_querySelect($sql,$rows);
          array_unshift($categories,$rows[0]["name"]);
        } while($id = $rows[0]["parent"]);
        $path = implode("/",$categories);
      }
    }
    $banner["breadcrumbs"] = array();

With that in place, continuing the above example;

example.com/cat/Smartphones/

...will internally re-build $path to show the same page as;

example.com/cat/Electronics/Communications/Smartphones/

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by Marcos on Tue, 2020-06-09 05:22

Hi David, hope you are doing well.

I would like to get shorter URLs and I tried the categories.php mod you proposed but I still seeing the same breadcrumb links configuration. Please let me explain in more detail

For the following breadcrumb structure:
Home / Category / Main Category / Subcategory

I have those links:
Home = domain.com
Category = domain.com/category/
Main Category = domain.com/category/Main-Category/
Subcategory = domain.com/category/Main-Category/Subcategory/

While I would like to have the following links keeping the same breadcrumb structure:
Home = domain.com
Category = domain.com/category/
Main Category = domain.com/Main-Category/
Subcategory = domain.com/Subcategory/

And I would like to have this in all pages, including product pages. Could you please help me putting this in place?

Thank you in advance.

Best,
Marcos

Submitted by support on Tue, 2020-06-09 08:06

Hello Marcos,

To do this for product and category URLs (bear in mind the caveat that all names in the hierarchy must be unique), from unmodified files first edit includes/tapestry.php and look for the following code at line 66:

      return $config_baseHREF."product/".urlencode(tapestry_hyphenate($product["normalised_name"])).".html";

...and REPLACE with:

      return $config_baseHREF.urlencode(tapestry_hyphenate($product["normalised_name"])).".html";

And then the following code at line 331:

    $href = $config_baseHREF.$indexHREF[$index][$config_useRewrite];

...and REPLACE with:

    if (($index=="category") && $entry)
    {
      $parts = explode("/",trim($entry,"/"));
      $entry = array_pop($parts);
      return $config_baseHREF.tapestry_hyphenate($entry)."/";
    }
    $href = $config_baseHREF.$indexHREF[$index][$config_useRewrite];

Next, edit categories.php and look for the following code at line 2:

  require_once("includes/common.php");

...and REPLACE with:

  require_once("includes/common.php");
  function getCategoryPath($id)
  {
    global $config_databaseTablePrefix;
    $categories = array();
    do {
      $sql = "SELECT name,parent FROM `".$config_databaseTablePrefix."categories_hierarchy` WHERE id = '".$id."'";
      database_querySelect($sql,$rows);
      array_unshift($categories,$rows[0]["name"]);
    } while($id = $rows[0]["parent"]);
    return implode("/",$categories);
  }

...and then look for the following code at line 31:

    $nodeInfo = tapestry_categoryHierarchyNodeInfo($path);

...and REPLACE with:

    if ($path)
    {
      $path = str_replace("-"," ",$path);
      $sql = "SELECT id FROM `".$config_databaseTablePrefix."categories_hierarchy` WHERE name = '".database_safe($path)."'";
      if (database_querySelect($sql,$rows))
      {
        $path = getCategoryPath($rows[0]["id"]);
      }
    }
    $nodeInfo = tapestry_categoryHierarchyNodeInfo($path);

Finally, edit .htaccess and add the following additional rules to the end of the file;

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ categories.php?path=$1 [L,B]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*).html$ categories.php?path=$1&page=$2&rewrite=1&%{QUERY_STRING} [L,B]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*).html$ products.php?q=$1&rewrite=1&%{QUERY_STRING} [B,L]

Hope this helps!

Cheers,
David.
--
PriceTapestry.com