You are here:  » change product to root with rewrite


change product to root with rewrite

Submitted by wilkins on Mon, 2010-03-01 15:09 in

Hi David

Starting a new project and want to make the product page in root ie site.com/productname.html rather than site.com/product/productname.html, is this possible, htaccess seems easy but are there may changes to the script for this to work.

Thanks

Brent

Submitted by support on Mon, 2010-03-01 15:22

Hello Brent,

It's generally straight forward - they key thing is to make sure that .htaccess takes into account any other actual files that may exist in your top level folder that might be confused with product URLs. RewriteCond can be used to get around this.

In your .htaccess, move the product/ rule from the beginning to the end of your .htaccess adjusting as required, and preceding it with the RewriteCond rules to prevent it from redirecting actual files or directories as follows:

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

With that in place, it's basically just a case of search and replacing:

product/

with nothing (leave the replace box empty) in the following files:

index.php
products.php
reviews.php
search.php
sitemap.php

Cheers,
David.

Submitted by Bigmac on Fri, 2011-04-08 08:18

Hi David,

I am using PT in a subfolder as WP is in root and would like to remove product from the url so the products would be at domain.com/pt/abc.html instead of domain.com/pt/product/abc.html.

Is this possible? I am using 12/10A and have tried the above but I can't find any instance of product/ in index.php or products.php.

Many thanks.

Hamish

Submitted by support on Fri, 2011-04-08 08:23

Hi Hamish,

Even easier in 12/10A as the product URL is generated by a function in includes/tapestry.php. After making the .htaccess changes as described above look for the following code at line 53:

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

...and REPLACE that with:

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

Cheers,
David.
--
PriceTapestry.com

Submitted by Bigmac on Fri, 2011-04-08 08:38

Thank you.

Tell me, is it as easy to force all urls to be lowercase?

Thanks again.

Cheers,

Hamish

Submitted by support on Fri, 2011-04-08 08:46

Hi Hamish,

Sure - use the following as the replacement:

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

Cheers,
David.
--
PriceTapestry.com

Submitted by Bigmac on Fri, 2011-04-08 09:07

Working nicely, thanks.

Am I right in saying I need to add (strtolower($product.....)) to categories.php, brands.php and merchants.php to make them lowercase, too?

Thanks again for your help.

Cheers,

Hamish

Submitted by support on Fri, 2011-04-08 10:00

Hi Hamish,

Correct, in each of those files you'll find this line (or similar):

  $item["href"] = urlencode(tapestry_hyphenate($product["category"]))."/";

...REPLACE with:

  $item["href"] = urlencode(tapestry_hyphenate(strtolower($product["category"])))."/";

Cheers,
David.
--
PriceTapestry.com

Submitted by Bigmac on Fri, 2011-04-08 10:07

Do you not mean

urlencode(tapestry_hyphenate(strtolower($product["category"])))."/";

Just thinking of someone else.

Cheers,

H

Submitted by support on Fri, 2011-04-08 10:09

Yes, sorry about that! Corrected above also...

Cheers,
David.
--
PriceTapestry.com

Submitted by Halion on Tue, 2014-01-21 22:03

Hi David,

Re your answer at the top of this thread about rewriting product page urls to root in .htaccess, I would also like to have brands and categories mapped to root in .htaccess too, as well as products. (Merchants and Reviews not necessary to change).

So

...co.uk/category/Arts-Crafts/ becomes ...co.uk/Arts-Crafts.html
...co.uk/brand/Sony/ becomes ...co.uk/Sony.html
...co.uk/product/teabags.html becomes ...co.uk/teabags.html

My current .htaccess (I am using version 12/10B) is :

{code saved}

Could you please show how this .htaccess file should be rewritten, and any further search and replaces I should do?

Many thanks in advance

Mike

Submitted by support on Wed, 2014-01-22 08:54

Hello Mike,

The first reply above refers to a few versions prior to 12/10B, and is is much easier modification now since the product URL is returned by a single function tapestry_productHREF(). The category and brand contractions need a little more consideration since there is nothing in the URL to indicate whether it is a category or a brand so this could have performance implications but it would be possible to add additional indexes if this is a problem.

Prepare a replacement .htaccess as follows (based on the distribution version, don't forget to replace any custom modifications such as your ErrorDocument directive etc.)

Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteRule ^product/(.*).html$ $1.html [L,R=301]
RewriteRule ^review/(.*).html$ reviews.php?q=$1&rewrite=1&%{QUERY_STRING} [L]
RewriteRule ^merchant/$ merchants.php
RewriteRule ^merchant/(.*)/$ search.php?q=merchant:$1:&rewrite=1&%{QUERY_STRING} [L]
RewriteRule ^merchant/(.*)/(.*).html$ search.php?q=merchant:$1:&page=$2&rewrite=1&%{QUERY_STRING} [L]
RewriteRule ^category/$ categories.php
RewriteRule ^brand/$ brands.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ search.php?q=catbrand:$1:&rewrite=1&%{QUERY_STRING} [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*).html$ search.php?q=catbrand:$1:&page=$2&rewrite=1&%{QUERY_STRING} [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*).html$ products.php?q=$1&rewrite=1&%{QUERY_STRING} [L]

Before uploading, apply code changes as follows (12/10B)

In includes/tapestry.php look for the following code around line 53:

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

...and REPLACE with:

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

In sitemap.php look for the following code at line 32:

  $sitemapHREF = "product/".urlencode(str_replace(" ","-",$row["normalised_name"])).".html";

...and REPLACE with:

  $sitemapHREF = urlencode(str_replace(" ","-",$row["normalised_name"])).".html";

In categories.php look for the following code at line 20:

  $item["href"] = urlencode(tapestry_hyphenate($product["category"]))."/"

...and REPLACE with;

  $item["href"] = $config_baseHREF.urlencode(tapestry_hyphenate($product["category"]))."/"

In brands.php look for the following code at line 20:

  $item["href"] = urlencode(tapestry_hyphenate($product["brand"]))."/"

...and REPLACE with;

  $item["href"] = $config_baseHREF.urlencode(tapestry_hyphenate($product["brand"]))."/"

And finally in search.php look for the following code at line 163:

      case "bw":

...and REPLACE with:

      case "catbrand":
        $where = "category = '".database_safe($parts[1])."' OR brand = '".database_safe($parts[1])."'";
        $sql = "SELECT SQL_CALC_FOUND_ROWS * , MIN( price ) AS minPrice, MAX( price ) AS maxPrice, COUNT( id ) AS numMerchants FROM `".$config_databaseTablePrefix."products` WHERE ".$where.$priceWhere." GROUP BY name";
        $orderBySelection = $orderByDefault;
        break;
      case "bw":

Cheers,
David.
--
PriceTapestry.com

Submitted by Halion on Wed, 2014-01-22 12:23

Hi David,

Thanks for your reply. I've started doing the search and replaces, but notice that for categories.php and brands.php the search and replace appear to be the same code. Is this right?

Cheers
Mike

Submitted by support on Wed, 2014-01-22 12:54

Sorry Mike, replacements for categories.php and brands.php corrected above.

Cheers,
David.
--
PriceTapestry.com

Submitted by Halion on Thu, 2014-01-23 09:10

Hi David, thanks for your reply. Product pages rewriting is working fine but categories and brands are rewriting to search.php?.... instead of, eg., ...co.uk/Sony.html as given in the example in my first post above on this thread.

Is this because as most times there will be more than one brand page for say, Sony, it is not possible to rewrite as ...co.uk/Sony.html , ...co.uk/Sony-2.html etc, or that it would be too heavy on resources?

Cheers

Mike

Submitted by support on Thu, 2014-01-23 09:44

Hello Mike,

Ah, I'd overlooked that in your original email sorry; but the above should be working with

...co.uk/Sony/

This is the way I normally apply this kind of modification as it leaves

...co.uk/Something.html

reserved for product pages.

This also makes pagination far more straight forward and works seamlessly with the existing
navigation code without modification, e.g.

...co.uk/Sony/
...co.uk/Sony/2.html
...co.uk/Sony/3.html

Let me know if that's all working with the above modifications in place (you can still browse brands and categories through /brand/ and /category/ as normal), and then if you would like to pursue an alternative structure I'll help you work towards that...

Cheers,
David.
--
PriceTapestry.com

Submitted by Halion on Thu, 2014-01-23 10:51

Hi David, thanks for your response. Will do and I'll report back later. I'm also going to check my search.php as it has been modified from the original (brand filter added).

Cheers
Mike

Submitted by Halion on Thu, 2014-01-23 16:18

Hi David,

Yes I rechecked, your modifications for categories and brands do as you suggest.

Thing is, I was hoping instead of .co.uk/Sony/ , .co.uk/Sony/2.html , .co.uk/Sony/3.html etc to get .co.uk/Sony.html , .co.uk/Sony-2.html , .co.uk/Sony-3.html etc as I hoped all category pages and brand pages could be kept to root.

I've reread your comments and it appears this might be considerably more complex to do. Would I be correct in that assumption? Your help is greatly appreciated and at this point would like to know your opinion before taking it further.

Submitted by support on Fri, 2014-01-24 10:52

Hi Mike,

First of all, create a redirection script called redir.php as follows to be the target of the initial rewrite, and which will decide whether to send the request to products.php or search.php:

<?php
  
require("config.php");
  function 
redir_normalise($text,$allow "")
  {
    global 
$config_charset;
    
$text str_replace("-"," ",$text);
    if (
$config_charset)
    {
      
$allow chr(0x80).'-'.chr(0xFF).$allow;
    }
    
$text preg_replace('/[^A-Za-z0-9'.$allow.' ]/e','',$text);
    
$text preg_replace('/[ ]{2,}/',' ',$text);
    return 
trim($text);
  }
  
$link mysql_connect($config_databaseServer,$config_databaseUsername,$config_databasePassword);
  
mysql_select_db($config_databaseName,$link);
  
$sql "SELECT * FROM `".$config_databaseTablePrefix."products` WHERE normalised_name = '".mysql_escape_string(redir_normalise($_GET["q"]))."'";
  
$result mysql_query($sql,$link);
  if (
mysql_num_rows($result))
  {
    require(
"products.php");
  }
  else
  {
    require(
"search.php");
  }
?>

Note: the following changes are based on distribution files rather than the previously described changes...

In categories.php look for the following code at line 20:

  $item["href"] = urlencode(tapestry_hyphenate($product["category"]))."/"

...and REPLACE with;

  $item["href"] = $config_baseHREF.urlencode(tapestry_hyphenate($product["category"])).".html"

In brands.php look for the following code at line 20:

  $item["href"] = urlencode(tapestry_hyphenate($product["brand"]))."/"

...and REPLACE with;

  $item["href"] = $config_baseHREF.urlencode(tapestry_hyphenate($product["brand"])).".html"

Now in html/navigation.php look for the following code at line 14:

  $prevHREF = "./";

...and REPLACE with:

  $prevHREF = tapestry_hyphenate($parts[1]).".html";

And then look for the following code at line 18:

  $prevHREF = $prevPage.".html";

...and REPLACE with:

  $prevHREF = tapestry_hyphenate($parts[1])."-".$prevPage.".html";

And then the following code at line 65:

  $pageOneHREF = "./";

...and REPLACE with:

  $pageOneHREF = tapestry_hyphenate($parts[1]).".html";

And then the following code at line 85:

  $pageHREF = $i.".html";

...and REPLACE with:

  $pageHREF = tapestry_hyphenate($parts[1])."-".$i.".html";

And finally the following code at line 109:

  $nextHREF = $nextPage.".html";

...and REPLACE with:

  $nextHREF = tapestry_hyphenate($parts[1])."-".$nextPage.".html";

And here's the .htaccess to go with the above changes:

Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteRule ^product/(.*).html$ $1.html [L,R=301]
RewriteRule ^review/(.*).html$ reviews.php?q=$1&rewrite=1&%{QUERY_STRING} [L]
RewriteRule ^merchant/$ merchants.php
RewriteRule ^merchant/(.*)/$ search.php?q=merchant:$1:&rewrite=1&%{QUERY_STRING} [L]
RewriteRule ^merchant/(.*)/(.*).html$ search.php?q=merchant:$1:&page=$2&rewrite=1&%{QUERY_STRING} [L]
RewriteRule ^category/$ categories.php
RewriteRule ^brand/$ brands.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)-([0-9]*).html$ redir.php?q=catbrand:$1:&page=$2&rewrite=1&%{QUERY_STRING} [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*).html$ redir.php?q=$1&rewrite=1&%{QUERY_STRING} [L]

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by Halion on Fri, 2014-01-24 12:54

Hi David,

Have uploaded changes and am getting :

Fatal error: Call to undefined function tapestry_normalise() in /redir.php on line 5

Any thoughts?

Cheers
Mike

Submitted by support on Fri, 2014-01-24 13:18

Hi Mike,

Corrected above! It can't use the library version as it would result in a duplicate function name...

Cheers,
David.
--
PriceTapestry.com

Submitted by Halion on Fri, 2014-01-24 13:55

Hi David,

Thanks v much for the update.

It's close. The .co.uk/Sony.html is working as is .co.uk/CategoryX.html, but the navigation , eg .co.uk/Sony-2.html , .co.uk/Sony-3.html is not.

Could you advise?

Cheers
Mike

Submitted by support on Fri, 2014-01-24 14:51

Hi Mike,

I've ran it all through on my test server, correct redir.php above, but primarily it was that html/navigation.php needed to use $parts[1] instead of $q, that, plus an additional replacement for line 14 corrected above...

Cheers,
David.
--
PriceTapestry.com

Submitted by Halion on Fri, 2014-01-24 15:11

Hi David, could it be that the mods you suggested for navigation.php are based on 13/03 and not 12/10B which is the one I'm using here? Just a thought as the line numbers suggest this?

Cheers
Mike

Submitted by support on Fri, 2014-01-24 15:46

Hi Mike,

12/10B mods to html/navigation.php:

Look for the following code at line 12:

  $prevHREF = $prevPage.".html";

...and REPLACE with:

  $prevHREF = tapestry_hyphenate($parts[1])."-".$prevPage.".html";

And then the following code at line 58:

  $pageOneHREF = "1.html";

...and REPLACE with:

  $pageOneHREF = tapestry_hyphenate($parts[1]).".html";

And then the following code at line 71:

  $pageHREF = $i.".html";

...and REPLACE with:

  $pageHREF = tapestry_hyphenate($parts[1])."-".$i.".html";

And finally the following code at line 95:

  $nextHREF = $nextPage.".html";

...and REPLACE with:

  $nextHREF = tapestry_hyphenate($parts[1])."-".$nextPage.".html";

Cheers,
David.
--
PriceTapestry.com

Submitted by Halion on Fri, 2014-01-24 16:07

Hi David,

Thanks very much for your updates, it's really appreciated. As you have tested that the mods are working ok on your server I'm going to do further testing here, (it's not quite working for me here), it may be something my end. Will report back.

Thanks again

Cheers
Mike

Submitted by support on Fri, 2014-01-24 16:12

Hi Mike,

No problem - if you want to post any example URLs, or alternatively email me your modified files and example links I'll check it all out for you...

Cheers,
David.
--
PriceTapestry.com

Submitted by sirmanu on Thu, 2016-09-22 13:30

Hi David.
Easy question regarding htacess.
I am doing test but I am not able to add the correct code.
What should I modify in order to have these urls working?

http://example.com/pricetapestry/brand
also
http://example.com/pricetapestry/brand/sony

Note that which work out of the box is
http://example.com/pricetapestry/brand/
http://example.com/pricetapestry/brand/sony/

I want to have both of them. with final slash or not. Also for merchant.

Thanks!

Submitted by support on Thu, 2016-09-22 13:34

Hi,

Do you want both versions to return the same page (consider duplicate content guidelines) or would you like without final slash to 301 (Moved Permanently) to with final slash? e.g.

http://example.com/pricetapestry/brand
301 Moved Permanently to:
http://example.com/pricetapestry/brand/

and

http://example.com/pricetapestry/brand/Sony
301 Moved Permanently to:
http://example.com/pricetapestry/brand/Sony/

Cheers,
David.
--
PriceTapestry.com

Submitted by sirmanu on Thu, 2016-09-22 13:45

Moved Permanently it seems to be easier as I don't want duplicate content. So it's okay.

Submitted by support on Thu, 2016-09-22 13:58

Hi,

To do this, add the following rules to the very _end_ of .htaccess

RewriteRule ^merchant$ merchant/ [L,R=301]
RewriteRule ^merchant/(.*)$ merchant/$1/ [L,R=301]
RewriteRule ^category$ category/ [L,R=301]
RewriteRule ^category/(.*)$ category/$1/ [L,R=301]
RewriteRule ^brand$ brand/ [L,R=301]
RewriteRule ^brand/(.*)$ brand/$1/ [L,R=301]

Cheers,
David.
--
PriceTapestry.com