I would like to make my urls more seo friendly and for example change this:
http://www.chillisource.co.uk/product?&cat=Grocery&q=Daves%20Gourmet&page=1&prod=B0000DID5R&prodName=Daves_Insanity_Sauce
to something nice like this:
http://www.chillisource.co.uk/product/Daves_Gourmet/Daves_Insanity_Sauce
What is the best way of going about doing this? I've had a look at doing this with the htaccess file but this seems very complicated.
Thanks in advance
Ben Paton, there is in fact a very easy way out. CMSes like Wordpress tend to use it instead of messing around with regular expressions.
The .htaccess
side
First of, you use an .htacess with the content below:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Let me explain what it does (line by line):
- if the apache module named mod_rewrite exists..
- turn the module on
- let it be known that we will rewrite anything starting after the
domain name (to only rewrite some directories, use
RewriteBase
/subdir/
)
- if the requested path does not exist as a file...
- and it doesn't even exist as a directory...
- "redirect" request to the index.php file
- close our module condition
The above is just a quick explanation. You don't really need it to use this.
What we did, is that we told Apache that all requests that would end up as 404s to pass them to the index.php file, where we can process the request manually.
The PHP side
On the PHP side, inside index.php
, you simply have to parse the original URL. This URL is passed in the $_SERVER
variable as $_SERVER['REDIRECT_URL']
.
The best part, if there was no redirection, this variable is not set!
So, our code would end up like:
if ( isset( $_SERVER['REDIRECT_URL'] ) ) {
$url = explode('/', $_SERVER['REDIRECT_URL'] );
switch($url[0]){
case 'home': // eg: /home/
break;
case 'about': // eg: /about/
break;
case 'images': // eg: /images/
switch( $url[1] ){
case '2010': // eg: /images/2010/
break;
case '2011': // eg: /images/2011/
break;
}
break;
}
}
Easy Integration
I nearly forgot to mention this, but, thanks to the way it works, you can even end up not changing your existing code at all!
Less talk, more examples. Let's say your code looked like:
<?php
$page = get_page($_GET['id']);
echo '<h1>'. $page->title .'</h1>';
echo '<div>'. $page->content .'</div>';
?>
Which worked with urls like:
index.php?id=5
You can make it work with SEO URLs as well as keep it with your old system at the same time. Firstly, make sure the .htaccess
contains the code I wrote in the one above.
Next, add the following code at the very start of your file:
if ( isset( $_SERVER['REDIRECT_URL'] ) ) {
$url = explode('/', $_SERVER['REDIRECT_URL'] );
$_GET['id'] = $url[0];
}
What are we doing here? Before going on two your own code, we are basically finding IDs and information from the old URL and feeding it to PHP's $_GET variable.
We are essentially fooling your code to think the request had those variables!
The only remaining hurdle to find all those pesky <a/>
tags and replace their href
accordingly, but that's a different story. :)
It's called a mod_rewrite, here is a tutorial:
http://www.workingwith.me.uk/articles/scripting/mod_rewrite
What about using the PATH_INFO
environment variable?
$path=explode("/",getenv("PATH_INFO"));
echo($path[0]."; ".$path[1] /* ... */);
Will output
product; Daves_Gourmet; Daves_insanity_Sauce
The transition from using $_GET
to using PATH_INFO
environment is a good programming exercise. I think you cannot just do the task with configuration.
try some thing like this
RewriteRule ^/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/([a-zA-Z0-9]+) /$1.php?id1=$2&id2=$3 [QSA]
then use $_GET
to get the parameter values...
I'll have to add: in your original url, there's a 'prod' key, which seems to consist of an ID.
Make sure that, when switching to rewritten urls, you no longer solely depend upon a unique id, because that won't be visible in the url.
Now, you can use the ID to make a distinction between 2 products with the same name, but in case of rewriting urls and no longer requiring ID in the url, you need to make sure 1 product name can not be used multiple times for different products.
Likewise, I see the 'cat'-key not being present in the desired output url, same applies as described above.
Disregarding the above-described "problems", the rewrite should roughtly look like:
RewriteRule ^/product/(.*?)/(.*?)$ /product?&cat=Grocery&q=$1&page=1&prod=B0000DID5R&prodName=$2
The q & prodName will receive the underscored value, rather than %20, so also that will require some patching.
As you can see, I didn't touch the id & category, it'll be up to you to figure out how to handle that.