Nonostante le tonnellate di esempi e documentazione, mod_rewrite è voodoo.
Voodoo dannatamente figo, ma sempre voodoo.
Piccola guida al mod_rewrite
- contiene le informazioni base da sapere per utilizzare questo utilissimo modulo. La guida anche se orientata ad Apache è ovviamente valida (per la parte teorica) ad IIS / ISAPI rewrite.
mod_rewrite
è un modulo per Apache, il webserver più usato nel mondo Unix. Il modulo associa "al volo" un URL virtuale (non residente sul filesystem) ad uno reale, tramite delle regole definite nei file .htaccess
Se sei in un hosting condiviso, non devi fare niente: il modulo è attivo di default nella maggior parte dei casi. In ogni caso prima di acquistare un piano d'hosting chiedi esplicitamente se il modulo è installato!
Se lavori invece su un tuo server dedicato / VPS / localhost, molto probabilmente devi attivare il modulo a mano:
a2enmod rewrite
come rootLoadModule mod_rewrite
nel file di configurazioneApache di default ignora i file .htaccess (e di conseguenza le tue regole!) - per farglieli leggere devi modificare la direttiva AllowOverride
all'interno del file di configurazione. Ricorda di riavviare il webserver.
Per controllare se il modulo funziona:
Livello 1) crea una pagina .php
<?php phpinfo(); ?>
Richiamala dal browser e cerca nella pagina mod_rewrite
sotto Loaded Modules. Se trovi la stringa, vuol dire che il modulo è caricato.
Livello 2) testare se effettivamente gli indirizzi vengono riscritti: scarica questo file e segui le istruzioni contenute nell'archivo stesso.
Riporto la struttura "base" di un file .htaccess contenente una semplice regola
RewriteEngine On RewriteRule ^index.html$ fooindex.php [L]
La prima linea attiva l'engine (va sempre inserita)
La seconda linea specifica una regola (RewriteRule) composta da:
Inserendo queste due righe in domain.tld/.htaccess, quando un utente visita domain.tld/index.html il webserver invia la pagina domain.tld/fooindex.php. L'utente non si accorge di niente.
- se fooindex.php non esiste, l'utente vede "404 fooindex.php", anche se ha richiesto index.html
Procediamo per casi analizzando alcuni URL-tipo che ognuno di noi ha incontrato almeno una volta. Sono solo degli esempi, riadattabili alle proprie esigenze. Il consiglio è di leggere in modo lineare tutti i casi, e non solo la parte finale.
Lo scenario è la sezione news di un sito.
Ricordate che in ogni file htaccess dovete inserire, prima delle regole, la direttiva RewriteEngine On
.
URL prima dell'intervento: www.domain.tld/news/index.php?id=1234
URL dopo l'intervento: www.domain.tld/news/notizia-1234.html
RewriteRule ^notizia-([0-9]+)\.html$ index.php?id=$1
Ok, abbiamo tolto la querystring (hai detto niente!). Ma non è proprio il sistema più raffinato e la semantica è a 0.
URL prima dell'intervento: www.domain.tld/news/index.php?id=1234&cat=recensione
URL dopo l'intervento: www.domain.tld/news/recensione-1234.html
RewriteRule ^(.+)-([0-9]+)\.html$ index.php?id=$2&cat=$1
URL prima dell'intervento: www.domain.tld/news/categoria.php?id=2
URL dopo l'intervento: www.domain.tld/news/recensioni.html
RewriteRule ^([^/]+)\.html$ index.php?nomecat=$1
$cat = $_GET['nomecat']; $categoria = mysql_query("SELECT id FROM categorie WHERE nome='$cat'"); if (mysql_num_rows($categoria)==0) { Make404(......); } else { $categoria = mysql_num_rows($categoria); $news = mysql_query("SELECT .... FROM news WHERE categoria='$categoria[0]'"); ShowNews(......); }
Nota bene: è possibile eliminare l'ID contenuto nell'URL se e solo se la corrispondenza ID<->stringa è biunivoca!
URL prima dell'intervento: www.domain.tld/news/index.php?id=1234
URL dopo l'intervento: www.domain.tld/news/recensioni/php6-usera-goto-1234.html
RewriteRule ^([^/]+)/([^/]+)-([0-9]+)\.html$ index.php?id=$3&cat=$1&titolo=$2
$newsid = $_GET['id']; // non serve fare il cast con (int) $news = mysql_query("SELECT ... FROM news WHERE id='$newsid'"); if (mysql_num_rows($news)==0) { Make404(......); } else { ..... // supponiamo di avere in $cat la categoria letta dal database // e in $titolo il.. titolo ovviamente if ($cat != $_GET['cat'] || ottimizza($titolo) != $_GET['titolo']) { // è stato cambiato titolo o categoria make301('http//www.domain.tld/news/' . $cat . '/' . $titolo . '-' . $newsid . '.html'); } NewsClass:ShowNews(......); }
La direttiva RewriteLog
permette di salvare l'output di debug di mod_rewrite
su un file, ma va inserita nel file di configurazione principale di Apache, e in un hosting condiviso ciò non è possibile.
Per vedere quali pezzi di url (e in che modo) vengono riconosciuti, basta usare uno script con questo semplice contenuto
<?php print_r($_GET);
RewriteRule ^(.+)-(.+)\.html$ debugger.php?id=$1&cat=$2
Richiamando nel browser la pagina test-123.html:
Array ( [id] => test [cat] => 123 )
capiremo di aver invertito $1 con $2.. ;)
Tre consigli:
mod_rewrite
le regole successive.
--Osvi 15:30, Lug 30, 2007 (CEST)