Tuesday, March 31, 2009

How To : SEO friendly URLs

When you are working with web portals SEO is almost a must now a days. And when you are working for SEO, seo friendly URL is what you should take care of. Again when you are playing with php and Apache following are the ways that you can utilize :
  • Using Apache mod_rewrite:
There is some debate as to whether or not this is actually a front controller design, since no index.php file is utilized. However, I thought it would be worthwhile to demonstrate how URL rewrites work at the highest level before moving onto advanced solutions. Remember, this is not the preferred approach, but it is a good primer. The following is an example of one-to-one relationship URL rewrites in an .htaccess. If you have less than a dozen pages on a small Web site, this can be a useful quick fix.
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteRule ^our-services/strategic-consulting$ /our_services.php?id=1 [L]
RewriteRule ^our-services/web-design$ /our_services.php?id=2 [L]
RewriteRule ^our-services/web-development$ /our_services.php?id=3 [L]
</ifmodule>

The IfModule conditional directive wraps a section of rewrite rules, and ensures that they will only get executed on a server that has mod_rewrite capabilities. If the module did not exist, and there was no conditional directive, users will receive an HTTP Error 500 - Internal Server Error. It is good practice to always use this directive.

According to the documentation, “The RewriteEngine directive enables or disables the runtime rewriting engine.” RewriteEngine can be declared multiple times within .htaccess, which can actually help with debugging. The directive can be turned on or off, and instead of commenting out or deleting a line during testing, it is best to use RewriteEngine Off. In the example there is only the need to turn the rewrite engine on once.

The RewriteRule directive is one of the most powerful aspects of mod_rewrite. I invite you to bookmark and eventually read the official documentation for RewriteRule. There are too many facets to this directive to cover them all, so I will mention just a few.

  1. RewriteRule uses pattern substitution through regular expressions. So, the more you know about regular expressions, the more powerful your rewrite rules can become.
  2. Each rule begins with RewriteRule, and multiple rules can be applied to a single URL string before the page request is passed along to a PHP (or other) file.
  3. Definition order is important. Top down is the order of execution. You cannot skip rules unless they are commented out.
  4. The first portion of a rule is the pattern to match. The caret anchor (^) designates the beginning of a pattern match (start of line). The dollar anchor ($) designates the end of a pattern match (end of line). (This is the URL that the user typed into the address bar.)
  5. The second portion of the rule designates the file path that should actually handle the request behind the scenes if, and only if, a pattern match was found in the first portion of the rule. You can use regular expression groups and backreferences to pass information from the first portion of the URL to the second portion of the URL. More on that later.
  6. The final portion of the rule is a flag. It provides additional flexibility without the use of further pattern substitutions. The flag in the example above is “last rule”, and states that if a match was found, no further rules should be processed. The request is then forwarded on to the application. Multiple flags can be separated by a comma, all of them contained between a single set of brackets.
  • Writing own PHP engine for URL translation:
Step 1.
In your .htaccess file (If you don't have one, then create a new one in the folder where your index.php resides) add the following:

<FilesMatch "index">
ForceType application/x-httpd-php
</FilesMatch>

This simply tells your apache server to treat "index" in the url as "index.php". If you are using a server other than apache, then you will need to configure it to do this.

Step 2.
Implement the class below so that an instance is create each time index.php is executed. What this does is it takes the special url www.mysite.com/index/menuID_28-type_article and
splits it into www.mysite.com/index/ and menuID_28-type_article strings, then it creates an array:
array['menuID'] = 28
array['type'] = article
You cannot use $_GET['paramName'], instead call getItem($key) method in UrlFilter passing the name of the parameter you want, for exaple: $this->urlFilter -> getItem("menuID").
You can use any number of parameters, and name them as you wish, all you have to do is use the getItem() method and you got yourself nice URLs. Ofcourse you will need to build your links correctly for this to work, use getOriginalUrl() for this, then add your parameters to it: /param_value-param2_value2-param3_value3 and so on...
// constructs search friendly urls and create correct url paths for links and images
class UrlFilter {
var $origUrl;
var $numOfItems;
var $itemsMap;

function UrlFilter()
{
$this->processURI();
$this->constructBaseUrl();
}

function processURI()
{
$array = explode("index", $_SERVER['PHP_SELF']);
$newUrl = str_replace("/", "", $array[count($array)-1]);
$array = explode("-", $newUrl);
$num = count($array);
$this->numOfItems = $num;
$url_array = array();

$items = explode("-", $newUrl);
$num = count($items);
for ($i = 0 ; $i < $num ; $i++) { $item = explode("_", $items[$i]); $this->itemsMap[$item[0]] = $item[1] ;
}
}

function constructBaseUrl()
{
// need to construct the original url
$array = explode("index", $_SERVER['PHP_SELF']);
$num = count($array);
$this->origUrl = "";
for ($i = 0; $i < $num-1 ; $i++) { $this->origUrl = $this->origUrl . $array[$i];
}
}

function getItem($key)
{
if (array_key_exists($key, $this->itemsMap)) {
return $this->itemsMap[$key];
} else {
return null;
}
}

function getOriginalUrl()
{
return $this->origUrl . "index";
}

function getBaseUrl()
{
return $this->origUrl;
}

}