Werken met rewrite URL’s

Erik-Jan Bulthuis

27 januari 2007

Netters.nl gebruikt mooie, beschrijvende URL’s. Het zal echter duidelijk zat dat de map http://netters.nl/url-maken-met-mod_rewrite (waaronder dit artikel lijkt te staan) niet bestaat. Zou dat wel zo zijn, dan zou onze server vol staan met inmiddels vele duizenden mapjes en ik ben er blij om dat dit niet zo is. Als je server op Apache draait kun je d.m.v. .htaccess deze mooie URL’s gebruiken. Het voordeel is uiteraard dat het er mooier uit ziet dan http://netters.nl/index.php?module=artikelen&catID=31&pageID=364, maar daarnaast is het ook goed voor je zoekmachineoptimalisatie (SEO). Waarom je het zou moeten gebruiken en hoe het werkt lees je in dit artikel.

Opmerking:
Hoe deze beschrijvende URL’s genoemd worden verschilt nogal eens. Ik gebruik de term “smart URL’s”, maar er zijn andere termen in omloop als “url formatting” of “canonical URL’s”. Deze URL’s worden herschreven met een Apache module genaamd mod_rewrite.

Waarom smart URL’s?

Er zijn meerdere redenen te bedenken waarom je met deze smart URL’s wilt werken. Ik noem er een paar:

  1. Smart URL’s zijn beter leesbaar voor mensen
    Met een URL als http://netters.nl/url-herschrijven-met-mod-rewrite weet je precies waar de pagina over gaat (tenzij je niet weet wat mod_rewrite is natuurlijk). Dit maakt het bookmarken en het doorsturen van links naar iemand anders makkelijker. Ook geeft het naast de paginatitel een korte samenvatting van de betreffende pagina.
  2. Smart URL’s zijn beter leesbaar voor zoekmachines
    Zoekmachines gebruiken de woorden binnen een URL als argument. Van een URL als http://www.site.nl/index.php?catID=4&subID=25 kan een zoekmachine geen kaas maken, maar een URL als http://www.site.nl/nieuws/wij-zijn-verhuisd-naar-arnhem is beschrijvend en bevat belangrijke zoektermen.
  3. Zoekmachines indexeren lange parameter-string niet
    Het blijkt dat zoekmachines URL’s met meer dan drie parameters niet of niet volledig indexeren. Ook URL’s met parameters met een waarde van meer dan 10 karakters kunnen mogelijk niet geïndexeerd worden. URL’s die herschreven zijn met mod_rewrite worden prima opgenomen.
  4. Zoekmachines indexeren één URL maar een aantal keer
    Het schijnt dat zoekmachine’s van sites met meerdere URL’s die beginnen als index.php? maar een aantal van deze pagina’s indexeren, omdat het in de ogen van zoekmachines gaat om dezelfde pagina’s. Dit wil je natuurlijk niet.
  5. Smart URL’s zijn platformonafhankelijk
    Als je ooit je site in platte HTML hebt geschreven met de homepage op http://www.site.nl/index.html dan is het lastig om later op PHP over te gaan, omdat de homepage dan opeens op http://www.site.nl/index.php komt te staan. Alle bezoekers die binnenkomen op index.html zul je dan moeten redirecten en dat is knap vervelend.
  6. Smart URL’s zijn estetisch gezien mooier
    Het is verschil tussen een URL vol parameters en een strakke URL met daarin een paar beschrijvende woorden zal duidelijk zijn. Dit is zeker niet het grootste argument voor smart URL’s, maar het is er zeker weten wel één.

Opmerking:
De oplossing die het CMS Joomla gebruikt voor smart URL’s is ronduit lelijk te noemen. Een typische URL van dit systeem ziet er als volgt uit: http://www.site.nl/component/option,com_joomlaboard/Itemid,26/. Hoewel dit wel rekening houdt met de voordelen 3, 4 en 5 van de voordelen die we hierboven noemden, wordt er totaal niks gedaan aan 1, 2 en 6. Het is wel een makkelijke manier van werken, maar eigenlijk half werk. Hoe zoekmachinevriendelijk een CMS zou moeten meespelen in de afweging of je een eigen CMS gaat bouwen of een bestaande gaat gebruiken.

Hoe werkt mod_rewrite?

Mod_rewrite is een tool van de Apache webserver. Met deze tool kun je URL’s herschrijven tot een andere URL. Om de server aan te geven dat je URL’s wilt gaan herschrijven, zul je eerst de rewrite-engine moeten aanzetten. Dat kan met deze code in je .htaccess file:

RewriteEngine On

Nadat je deze regel hebt geplaatst, zijn er twee opties. Je kan er voor kiezen om in de .htaccess de URL’s te rewriten, maar je kan er ook voor kiezen hiervoor PHP te gebruiken. In de praktijk heb ik ervaren dat optie twee makkelijker is. Ik zal echter beide opties langslopen.

Rewriten in .htaccess

Om te rewriten in .htaccess start elk commando met het woord RewriteRule. Een geldige rewrite rule is bijvoorbeeld:

RewriteRule ^nieuws/(.*)/ page/nieuws.php?nieuwsID=$1

Als je nu een pagina /nieuws/1/ zou aanroepen, zou .htaccess deze doorsturen naar page/nieuws.php?nieuwsID=1. Je zult snappen dat dit prima werkt, maar het is de vraag of het gewenst is een behoorlijke lijst van deze RewriteRules op te nemen in je .htaccess. Elke keer als je nieuwe URL’s aanmaakt, zul je een regel moeten toevoegen in je .htaccess en dat is niet optimaal handig.

Rewriten in PHP

De andere optie waar ik dus vaak voor kies is om het redirecten in PHP te doen. Dit betekent dat ik elke pagina request doorstuur naar een PHP bestand en dat aan de hand van de URL wordt bepaald welke PHP-file moet worden included. Uiteraard moeten request voor .gif, .css, .jpg enz. files niet doorgestuurd worden naar dat PHP script, dus die include ik op deze manier:

RewriteEngine on

RewriteRule !.(gif|jpg|png|css|js)$ /home/httpd/vhosts/site.nl/httpdocs/site.php

Met deze code wordt elk request doorgestuurd naar het bestand site.php. Aldaar bepaal ik aan de hand van de URL of de URL daadwerkelijk verwijst naar een fysiek bestand of dat ik aan de hand van de URL een bepaalde pagina moet inladen. Dit doe ik met de volgende code:

// Kijk of het bestand zelf bestaat
if( file_exists($_SERVER['DOCUMENT_ROOT'] . $_SERVER['REQUEST_URI'])
AND ($_SERVER['SCRIPT_FILENAME'] != $_SERVER['DOCUMENT_ROOT'] . $_SERVER['REQUEST_URI'])
AND ($_SERVER['REQUEST_URI']!="/")){

$url = $_SERVER['REQUEST_URI'];
include($_SERVER['DOCUMENT_ROOT'] . $url);

}

// Pak de parameters van de URL
$url = strip_tags($_SERVER['REQUEST_URI']);
$url_array = explode("/",$url);
array_shift($url_array); // De eerste is leeg

if ($url_array[0] == "home"){

$include = "pages/index.php";

}elseif ($url_array[0] == "nieuws"){

if ($url_array[1]){
// Er is een nieuwsbericht, ID opslaan
$nieuwsID = $url_array[1];
}

$include = "pages/nieuws.php";

}elseif ($url_array[0] == "404"){

$include = "pages/404.php";

}

// Als er geen pagina geselecteerd is, gaan we de 404 laten zien
if (!isset($include)){
header('location:/404/');
}

include('include/header.php');
include($include);
include('include/footer.php');
?>

Opmerking:
Uiteraard kunnen er bepaalde mappen zijn die je niet langs site.php wilt sturen en die je wilt excluden in je .htaccess. Als je bijvoorbeeld je statistieken wilt excluden, kan dat op deze manier:

RewriteEngine on

RewriteRule ^stats/.*$ - [L]
RewriteRule ^stats/$ - [L]
RewriteRule ^stats$ - [L]

RewriteRule !.(gif|jpg|png|css|js)$ /home/httpd/vhosts/site.nl/httpdocs/site.php