Costruirsi un permalink usabile con .htaccess ed il mod_rewrite

Una delle cose più importanti di un’applicazione web pubblica è la scelta del formato dei link. Per capire il motivo di tale importanza è bene dire che quando si parla di applicazione web pubblica si fa riferimento a contenuti di tipo html creati dinamicamente e destinati ad un pubblico ampio e indefinito.

Questo vuol dire che possiamo disinteressarci della cosa se l’applicazione web in costruzione non ha motivi prettamente divulgativi. Se produciamo un software web based per la gestione delle prenotazioni di un albergo, non ci interesserà scegliere un formato particolare per i link.

In sostanza si capisce come il discriminante fra il porsi il problema o meno sia dato dall’utenza potenziale dell’applicazione.

Ma facciamo un ulteriore passo indietro. Chiediamoci perchè è giusto porci il problema. La risposta è molto semplice πŸ™‚

Nelle applicazioni web definite dinamiche, le pagine non esistono fisicamente. Così per questo blog non esiste una pagina statica scritta in linguaggio HTML per ogni post. Allo stesso modo i commenti non sono integrati fisicamente nella pagina, ma tutto il contenuto del blog viene estratto da un database (nel mio caso MySQL) e creato sul momento in base alle direttive date dal sistema.

Di fatto questa pagina non esiste. E’ solo la risultanza di una richiesta inviata al server da voi che leggete l’articolo. Non vi siete accorti di aver chiesto qualcosa al server vero? Eppure lo avete fatto. E sapete tramite cosa? Tramile il permalink di questo post πŸ™‚ . Nel link ci sono le direttive che verranno usate dal sistema per creare la pagina che state leggendo. In termini tecnici si dice che l’URL è una query string. Per farla semplice, l’URL non punta ad una posizione fisica individuata sul server, ma chiama l’esecuzione di un programma in funzione dei parametri contenuti nelle query string stessa.

Non ci state capendo una mazza? Basta fare un esempio facile facile! Sempre rimanendo in casa, in questo blog integro anche la versione mobile con layout ultra leggero per la massima accessibilità da dispositivi mobili (cellulari ed altro). Per accedere alla versione mobile del blog dovete digitare questo indirizzo:

http://www.davidonzo.com/?mobile=1

Che scritto più compiutamente diventa:

http://www.davidonzo.com/index.php?mobile=1

Il permalink di un post della versione mobile è qualcosa del genere:

http://www.davidonzo.com/index.php?post=681&mobile=1

Come vedete in tutti i casi chiamo il file index.php, che utilizzerà le variabili inviate via GET: l’id del post e l’attivazione della visualizzazione mobile.

Non esiste fisicamente la pagina richiesta. Questa viene creata all’istante tramite una query string adeguata. Ma tale tecnica, in funzione di ottimizzazioni SEO, ha molte controindicazioni.

Ai motori di ricerca non piacciono le query string. Sono la prova che il contenuto della pagina è dinamico. In altre parole una query string dice al motore di ricerca "Hey, stai attento ad indicizzare certi contenuni, perchè la pagina non esiste fisicamente ed il suo contenuto può cambiare facilmente. Stai acquorto!"

Questo produce un rallentamento dell’indicizzazione. Nonostante nella maggior parte dei casi il permalink di un post sia sinonimo di contenuto sempre uguale, i motori di ricerca tendono a non fidarsi.

Altro aspetto, secondo me meno rilevante, ma pur sempre da considerare, è la reazione dell’utente ad un link pieno di parametri, alcuni dei quali potrebbero apparire poco convincenti.

In ultimo, i motori di ricerca indicizzano come elementi primari di una pagina, l’attributo title ed il link. Se in quest’ultimo possono esserci elementi buoni di indicizzazione, sarà meglio per tutti!

Come sistemare la situazione? Ci sono diversi modi, ma il più semplice ed allo stesso tempo, potente c’è dato da Apache. Ovviamente se non utilizziamo Apache quello che segue è abbastanza inutile πŸ™‚

Per un giusto utilizzo dobbiamo controllare che il mod_rewrite sia attivano sul web server e che le direttive di Override permettano al file .htaccess di lavorare adeguatamente. Un AllowOverride All ci da la certezza di poter usare appieno il file .htaccess πŸ˜‰

Una volta controllato che il mod_rewrite sia abilitato e controllato anche che le impostazioni di override diano i poteri necessari al magico file di Apache, possiamo cominciare a scrivere il nostro .htaccess. Per prima cosa dobbiamo attivare il mod_rewrite, dire ad Apche di seguire i link simbolici e determinare la directory base in cui verrà eseguito il rewrite. In cima al file scriveremo:

[MORE] 

RewriteEngine On
Option +FollowSymLinks
RewriteBase /

Ora si stia attenti ad un concetto fondamentale. Spesso quando si parla di rewrite si intende la tecnica con la quale si riscrive una query string in formato che chiameremo friendly permalink. In realtà facciamo esattamente l’opposto!

Scriviamo e facciamo cliccare su permalink di tipo tradizionale, senza parametrizzazione, con indicazione di directory varie, ma grazie al lavoro del mod_rewrite questo verrà riscritto ed interpretato dal server in formato query string. Formato necessario perchè la nostra applicazione web possa interpretare nel giusto modo la richiesta del client.

Per cui diremo al webserver come riscrivere il permalink friendly in formato query string. Utilizzeremo istruzioni di questo tipo:

RewriteRule ^prova/([^/\.]+)/?$ index.php?prova=$1 [L]

Di fatto andiamo ad utilizzare la sintassi usata nelle espressioni regolari. Nell’esempio di sopra diciamo al webserver che un URL di tipo http://www.miosito.com/prova/qualcosa/ dovrà essere interpretato come http://www.miosito.com/index.php?prova=qualcosa.

Fin qui è abbastanza semplice. Scomponiamo la riga:

RewriteRule: il comando che fa capire ad Apache che stiamo per impartire una regola

  • ^prova/(^/\.+)/?$: il link da riscrivere in cui diciamo che sarà formato da una directory /prova/ seguito da un valore e terminante per /
  • index.php?prova=$1: l’indirizzo da interpretare.
  • [L]: il flag che interrompe il persing delle regole nel momento in cui questa va a buon fine.

In un file .htaccess possono esserci tutte le regole di rewrite che vogliamo. Utilizzando il flag [L] siamo sicuri che la regola che va a buon fine farà partire la richiesta al webserver senza seguire ulteriormente il file stesso.

Ma stiamo attenti, se è vero che possiamo inserire tutte le regole che vogliamo, è pur vero che un file .htaccess troppo carico di regole potrebbe rallentare il lavoro di Apache ed ingolfare la navigazione.

Un modo per far convivere regole molto simili a condizioni diverse è l’uso del comando RewriteCond. Equivale al flusso if di molti linguaggi di programmazione. Se si verifica la condizione necessaria, allora si attiva la regola di rewrite. Di seguito un esempio:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /404.html [L]

La regola dice che se il file (-f) o la directory -d non esistono (il ! è una negazione), reindirizziamo al file 404.html. E’ solo un esempio. Chiaramente per fare la stessa cosa in modo molto più semplice basterà usare la direttiva:

ErrorDocument 404 /404.html

Era giusto per spiegare il concetto πŸ™‚

Ora provete voi! Con il vostro editor di testo preferito create due file:

– index.php che conterrà:

<?php
  echo ‘<h1>’ . $_GET[‘prova’] . ‘</h1>’;
?>

– .htaccess che conterrà

Options +FollowSymLinks
RewriteEngine On

#Modificalo in funzione della tua webdirectory!
RewriteBase /

RewriteRule ^prova/([^/\.]+)/?$ index.php?prova=$1 [L]

Accedi digitando http://www.tuosito.com/prova/ciao/. Se visualizzerai:

Ciao

Avrai fatto tutto come si deve πŸ˜‰

NB: questo è solo un miliardesimo di quello che si può fare con .htaccess. La guida su apache.org resta il riferimento base!

17 thoughts on “Costruirsi un permalink usabile con .htaccess ed il mod_rewrite”

  1. questa cosa dei parametri nei motori di ricerca ormai è un po' obsoleta. Indicizzano praticamente tutto coi medesimi tempi, basta che ci sia una buona struttura di link.

    Piuttosto, sarebbe interessante sapere come gestire la presenza del rewrite A PRESCINDERE. Mi spiego:

    se faccio un sito con link dinamici e poi voglio passare a link riscritti, devo cambiare TUTTI i link. WordPress, ad esempio ma non solo, funziona sia se attivo il permalink sia se lo disattivo, perché genera i link a seconda che il rewrite sia attivo o no. come lo capisce? come genera gli url? come posso replicare questa cosa sui miei siti smarzi? πŸ™‚

  2. Obsoleta si, ma dipende da come ti costruisci il permalink. Se passi da

    sito.com/?var=10&var2=15&var3=18

    a

    sito.com/var/10/var2/16/var3/18/

    Praticamente non hai vantaggi se non quelli psicologichi dei pochissimi che leggono l'URL.

    Però se costruisci un permalink sostituendo o aggiungendo ad elementi inutili per la causa SEO (solitamente numerici) con elementi testuali di senso compiuto (il WP il post slug) allora il mod_rewrite ti aiuta non poco.

    WP genera il permalink in funzione dell'opzione di rewrite. Se disattivata va in default con la query string, altrimenti lo genera con il codice incluso nel file /wp-include/rewrite.php.

    E wp è intelligente ed ha il miglior SEO che abbia mai visto. Non a caso propone sempre il post slug come friendly permalink. Poi l'utente se vuole cambia, ma non ha tanto senso usare l'id del post, a quel punto si usi la query string, le cose non cambiano di molto.

    C'è un ultima cosa che mi preme: la scelta del permalink è meglio farla a priori. Se uso query string da due anni e da un giorno all'altro cambio struttura dei permalink, di sicuro non ci guadagnerò πŸ™‚

  3. ciao a tutti,

    dall'amministratore del server in cui risiedo in hosting linux ho avuto questa risposta

    Citazione:

    Gentile cliente,

    non tutte le direttive .htaccess (in particolare per il mod_rewrite) sono abilitate in hosting linux condiviso.

    Nel suo caso, l'opzione che crea problemi è la Options +FollowSymLinks.

    C'è da dire che alcuni CMS, come word-press e joomla, riescono ad abilitare la riscrittura amichevole dell'URL sfruttando delle classi php interne.

    secondo voi è possibile una soluzione che mi possa far riscrivere l'url

    io stavo pensando qualcosa del genere. IL PUNTO UNO l'ho testato e funziona

    ora vorrei modificarlo con il PUNTO 2. è fattibile? o mi conviene qualche altra strada?

    grazie dei vostri suggerimenti.

    [code]## esempio 2

    ## redirigo tutte le richieste da index.php a http://www.sito.com

    RewriteEngine on

    RewriteBase /testing/

    PUNTO 1 –>RewriteRule ^index.php$ http://www.testing.com/$1 [R,L]

    PUNTO 2 –>RewriteRule ^$1.php$ http://www.testing.com/pagina.php?path=$1 [R,L]

    [/code]

    cioè vorrei che scrivendo l'indirizzo http://www.test.it/URL-AMICHEVOLE.php

    il motore mi andasse a leggere il file http://www.test.com/pagina.php?path=URL-AMICHEVOLE.php

  4. Ciao Daniele.
    E' difficile dare una risposta su due piedi senza sapere il reale funzionamento del sistema.

    Prova in questo modo:
    RewriteRule ^([^/.]+).php pagina.php?path=$1 [L]

  5. ciao Davide,

    grazie.

    ho provato a fare in questo modo secondo le tue indicazioni

    [——]

    RewriteEngine on

    RewriteBase /testing/

    RewriteRule ^([^/.]+) localita.php?pathpagina=/localita/$1 [L]

    [——]

    nella pagina localita.php la select è come segue:

    [——]

    $mysqlc->query("SELECT * FROM tab WHERE pathpagina='".$_GET['pathpagina']."';");

    $result1 = mysql_fetch_array($mysqlc->result, MYSQL_ASSOC);

    [——]

    PERò come vedi dalla pagina che scrivo in basso, la pagina si apre correttamente ma non viene popolata, perchè probabilmente non passa il valore in query. ( http://www.marcocarra.it/testing/lecce )

    nel db il pathpagina è scritto esattamente così /localita/lecce

    che pensi?

  6. Prova in questo modo:

    RewriteRule ^([^/.]+)/?$ localita.php?pathpagina=/localita/$1 [L]

    Ho provato in locale con un semplice $_GET e funziona.

  7. CIAO DAVIDE,

    ok ora funziona. ho anche corretto un'anomalia nel db… quindi va

    ho però provato a mettere una sottodirectory nel rewrite il file non lo trova più. ho scritto così

    RewriteRule ^([^/.]+)/?$ localita.php?pathpagina=/localita/$1 [L]

    RewriteRule ^localita/([^/.]+)/?$ localita.php?pathpagina=/localita/$1 [L]

    per la prima riga il link sarà http://www.marcocarra.it/testing/lecce e funziona

    per la seconda riga il link sarà http://www.marcocarra.it/testing/localita/lecce ma non funziona

  8. Prova così:

    RewriteRule ^localita/([^/.]+)/?$ localita.php?pathpagina=/localita/$1 [L]
    RewriteRule ^([^/.]+)/?$ localita.php?pathpagina=/localita/$1 [L]

    Scrivi prima la regola con la sottodirectory riscritta.
    Appena ho due minuti faccio qualche prova. Ora sono in ufficio:)

  9. ciao mi dispiace se ti rompo…

    la sottodirectory riscritta non va ancora

    ricordo che l'OPTION +FollowSymLinks in aruba hosting linux condiviso non è attiva (come si diceva nel primo post…)

    ma perchè senza sottodirectory funziona? boh !!!

    ovviamente io ho bisogno di distinguere le query per attribuire il giusto path

  10. Daniele, non usare localita. Usa citta

    RewriteRule ^([^/.]+)/?$ localita.php?pathpagina=/localita/$1 [L]
    RewriteRule ^citta/([^/.]+)/?$ localita.php?pathpagina=/localita/$1 [L]

    tuosito.com/citta/lecce

    Così funziona.

  11. ciao davide,

    finalmente sto chiudendo il restyle del mio sito. Le tue indicazioni sono state davvero illuminanti.

    l'ultimo elemento che sto valutando senza venirne a capo è questo.

    vorrei costruire il link in questo modo:

    echo "<a href='salento/$tipologianome/vacanza-in-$localita$path'><img src=img/Salento_str".$id."_".$fotina."' height='67' width='90' title='$nome'></a></td>";

    quindi verrebbe fuori un indirizzo del genere

    http://www.viagginelsalento.it/salento/Hotel/vacanza-in-Lecce/Nome-Hotel

    ed ho costruito il file .htaccess così:

    RewriteRule ^salento/$1/$2/$3/([^/.]+)/?$ strutture.php?path_strutture=/$4 [L]

    ho provato diverse combinazioni ma niente.

    funziona solo se scrivo il link così:

    echo "<a href='salento/$path'><img src='img/Salento_str".$id."_".$fotina."' height='67' width='90' title='$nome'></a></td>";

    risultato indirizzo: http://www.viagginelsalento.it/salento/soluzioni-vacanza/Nome-Hotel

    quindi

    RewriteRule ^salento/soluzioni-vacanza/([^/.]+)/?$ appartamenti.php?path_strutture=/$1 [L]

    da quello che capisco non mi interpreta le variabili nel link della prima pagina

    indizi?

    grazie ancora, daniele

  12. ciao e grazie a questo in teressante post forse riesco a risolvere il mio problema di riscrittura delle url sul mio sito su server tomcat.

    Ho fatto la prova con la pagina "ciao" quindi ho risconrato che htaccess funziona.

    Avrei adesso la necessità di riscivere tutte le url che hanno questa forma:
    http://www.ciccio.com/tomcat/getProdotti.do?idprodotto=7&idsottocategoria=1

    Vorrei però partire dall'home page, infatti caricando il sito viene scritta questa url:
    xxx.com/tomcat/indexRedirect.do

    come posso scrivere per impostare l'homepage in modo che si abbia sempre http://www.ciccio.com ?

    grazie 1000 e spero in Voi per risolvere questo problema x me invalicabile… πŸ™

  13. Questo post mi è stato veramente utile, ma è sorto un problema.

    RewriteRule ^([^/.]+)/?$ index.php?page=$1

    qua tutto ok, ma se voglio aggiungere un'altra stringa per ottimizzare i link di un'altra pagina che non sia l' index.php, non funziona.

    RewriteRule ^([^/.]+)/?$ tools.php?page=$1

    mi spiego meglio, se io aggiungo queste 2 stringhe per il permalink, funziona solo il rewrite alla index, mentre non quello alla pagina tools.php, riportandomi alla homepage. qualcuno ha una soluzione?

Comments are closed.