Script Apache/PHP pour gérer les adresses simplifiées
Par KrisDevParis le samedi, janvier 15 2011, 13:43 - Lien permanent
Une adresse URL simplifiée, c'est utiliser http://www.surmonsite.com/afficher/mangez-des-pommes au lieu de http://www.surmonsite.com/afficher/affiche.php?article=157
C'est donc plus classe, au prix de quelques bouts de code un peu indigestes. La méthode exposée ici crée une page captive dans laquelle il sera possible de traiter toutes les requêtes inconnues. Cette page inclura ensuite le bon fichier php de votre site, en fonction de la requête et des fichiers existants sur votre site.
Pré-requis:
- Un site qui tourne sur un serveur Apache et en PHP
- La possibilité de modifier les fichiers .htaccess (directive AllowOverride All au bon endroit dans Répertoire Apache/conf/httpd.conf)
- L'activation du mod_rewrite dans Apache (ligne LoadModule rewrite_module modules/mod_rewrite.so non diésée dans Répertoire Apache/conf/httpd.conf)
Ces pré-requis sont généralement couverts avec tout hébergeur de qualité.
Etape 1: Mettre en place une redirection par défaut
Pour faire ça, on va mettre en place une page captive à la racine du site qui a pour rôle d'absorber toutes les requêtes... ou presque toutes, car vous n'avez pas envie que les images de votre site, ou votre répertoire perso contenant vos mp3 de Christophe Maé, soient redirigés vers cette page.
Créer un fichier .htaccess à la racine du site avec le contenu:
# KrisDevParis - Simplified URLs [Apache Handler] # Get the requested root directory or file SetEnvIfNoCase Request_URI "^/([A-Z0-9_\-]+)/" rootdir=$1 SetEnvIfNoCase Request_URI "^/([A-Z0-9_\-]+)$" rootdir=$1 SetEnvIfNoCase Request_URI "^/([^/]+)$" rootfile=$1 # If the user asked for a root file or a root directory that really exists, then don't do anything in particular (i.e. the user will access it normally) # Otherwise... RewriteEngine on RewriteCond %{DOCUMENT_ROOT}/%{ENV:rootdir} !-d RewriteCond %{DOCUMENT_ROOT}/%{ENV:rootfile} !-f # ... bring the user to a "catch all" page and exit. # + Append the eventuel query string to the "catch all" page. # + Stop the rewriting process (L). RewriteRule ^.*$ index.php [L,QSA] # You can then parse the $_SERVER['REQUEST_URI'] in PHP. <Directory /use> Order Deny,Allow Deny from All </Directory>
Etape 2: Exemple de page captive
Créer un fichier index.php à la racine du site avec comme contenu:
<?php /* WHERE AM I ? - KrisDevParis */ class WhereAmI { public $lev=array(); public $path=""; public $url=""; public $args=""; public function find($uri) { $uri=preg_replace('/[\\?#].*$/',"",$uri); $rawuri=explode("/",$uri); unset($rawuri[0]); $uri=preg_replace('/[^a-zA-Z0-9\\-_\\/]/i','',$uri); // Ne surtout pas autoriser les points! $uri=explode("/",$uri); unset($uri[0]); $this->path="use/"; $ok="init"; foreach($uri as $k=>$v) { if(!$v) continue; if($ok=="found" || $ok=="unfound") { // broken > get args $this->args[]=rawurldecode($rawuri[$k]); } elseif(is_dir($this->path.$v)) { $this->url.=$v."/"; $this->path.=$v."/"; $this->lev[]=$v; $ok="half"; } elseif(is_file($this->path.$v.'.php')) { $this->url.=$v; $this->path.=$v.'.php'; $this->lev[]=$v.'.php'; $ok="found"; //break; } else { $ok="unfound"; //break; } } if($ok=="half" || $ok=="unfound" || $ok=="init") { // Try to find index.php in the (eventually) found dir - doesn't apply if a file has been found. if(is_file($this->path.'index.php')) { //$this->url.=""; $this->path.='index.php'; $this->lev[]='index.php'; $ok="found"; } else $ok="unfound"; } //debug($this); if($ok == "unfound" || count($this->lev) == 1 || $ok=="init") { // Redirect either to the site homepage or 404 error. The homepage CANNOT have args. if(count($this->lev) == 1) { $this->lev=array("index.php"); $this->path="use/index.php"; $this->url=""; return false; } else { // 404 are thrown only for dirs without index.php or the root dir, otherwise params are considered as index.php's args $this->lev=array("@errors","404.php"); $this->path="use/@errors/404.php"; $this->url=""; } } else return true; } } // End WhereAmI $here = new WhereAmI(); $here->find($_SERVER['REQUEST_URI']); // Inclure la page include_once($here->path); ?>
Comment ça marche?
Désormais, votre site suit la répartition du dossier /use ! Restriction: les noms de répertoire ou de fichier ne peuvent contenir que les caractères a-z, A-Z, 0-9, le tiret (-) et le tiret bas (_).
http://www.monsite.com/test → inclut use/test/index.php s'il existe, ou use/test.php s'il existe, sinon vers use/@errors/404.php
http://www.monsite.com/test/blablabla → de même, inclut use/test/index.php à supposer qu'il existe. Vous pouvez dans cette page exploiter $here->args[0] = "blablabla"
%% http://www.monsite.com/test/blablabla?hehe=10 → de même, inclut use/test/index.php à supposer qu'il existe. Vous pouvez dans cette page exploiter $here->args[0] = "blablabla". La variable $_GET["hehe"]=10, comme on pouvait s'y attendre. %%