Il mod_rewrite e la magia di riscrivere gli URL (seconda parte)

Nella prima parte di questo articolo abbiamo visto due esempi molto semplici di rewrite dell’url. Quello che faremo adesso sarà inserire il nome del prodotto nell’url. Perchè?
Dato che l’url riscritto sarà quello registrato dal motore di ricerca, diventa estrememente interessante visualizzare il nome del prodotto nell’url.
Un aspetto al quale dovremo prestare particolare attenzione riguarda il limite per cui la stringa di un url non ammette spazi e caratteri speciali o accentati. Dovremo dunque passare la stringa che rappresenta il nome del prodotto in un “filtro” che sostituisca gli spazi con dei trattini, le lettere accentate con le corrispondenti non accentate e che elimini gli eventuali caratteri speciali.
Che tipo di url vogliamo ottenere per ottimizzare l’indicizzazione?
Quello che vogliamo ottenere é un url di questo genere:
http://www.tuosito.com/prodotto56/tosa-erba-elettrico-grande
Se non utilizzassimo l’url rewrite, la costruzione del link per visualizzare i dettagli del prodotto, sarebbe simile a questa
//lettura dei valori dal database echo '<a href="prodotti.php?id=' . $id . '">' . $nomeProdotto . '</a>';
Se vogliamo produrre un url come quello visto in precedenza dovremo invece procedere in questo modo:
//lettura dei valori dal database //filtraggio del nome prodotto echo '<a href="prodotto' . $id . '/' . $nomeProdottoFiltrato . '">' . $nomeProdotto . '</a>';
Come abbiamo visto all’inizio, se vogliamo passare il nome prodotto nell’url, dovremo prima ripulirlo da lettere accentate e caratteri speciali che potrebbero creare problemi e successivamente sostituire anche gli spazi con dei trattini.
Ripuliamo il nome del prodotto che vogliamo passare come url
Creiamo la funzione CleanString() ed iniziamo a rimpiazzare le lettere accentate con le medesime lettere ma senza accenti utilizzando la funzione str_ireplace().
function CleanString($string)
{
$strResult = str_ireplace("à", "a", $string);
$strResult = str_ireplace("á", "a", $strResult);
$strResult = str_ireplace("è", "e", $strResult);
$strResult = str_ireplace("é", "e", $strResult);
$strResult = str_ireplace("ì", "i", $strResult);
$strResult = str_ireplace("í", "i", $strResult);
$strResult = str_ireplace("ò", "o", $strResult);
$strResult = str_ireplace("ó", "o", $strResult);
$strResult = str_ireplace("ù", "u", $strResult);
$strResult = str_ireplace("ú", "u", $strResult);
$strResult = str_ireplace("ç", "c", $strResult);
$strResult = str_ireplace("ö", "o", $strResult);
$strResult = str_ireplace("û", "u", $strResult);
$strResult = str_ireplace("ê", "e", $strResult);
$strResult = str_ireplace("ü", "u", $strResult);
$strResult = str_ireplace("ë", "e", $strResult);
$strResult = str_ireplace("ä", "a", $strResult);
Sostiuiamo anche l’apostrofo con uno spazio:
$strResult = str_ireplace("'", " ", $strResult);
Ora possiamo rimuovere tutto quello che non è un carattere normale o un numero:
$strResult = preg_replace('/[^A-Za-z0-9 ]/', "", $strResult);
In seguito rimuoviamo eventuali spazi prima e/o dopo la stringa con la funzione trim():
$strResult = trim($strResult);
Adesso una piccola rifinitura. Se mai dovessero esserci dei doppi (o più) spazi all’interno della stringa, riduciamoli ad un solo spazio:
$strResult = preg_replace('/[ ]{2,}/', " ", $strResult);
L’espressione regolare precedente trova tutto quello che è due o più spazi e li sostituisce con un solo spazio.
Ora non ci resta che sostituire gli spazi con dei trattini:
$strResult = str_replace(" ", "-", $strResult);
Ed ecco la nostra funzione
function CleanString($string)
{
$strResult = str_ireplace("à", "a", $string);
$strResult = str_ireplace("á", "a", $strResult);
$strResult = str_ireplace("è", "e", $strResult);
$strResult = str_ireplace("é", "e", $strResult);
$strResult = str_ireplace("ì", "i", $strResult);
$strResult = str_ireplace("í", "i", $strResult);
$strResult = str_ireplace("ò", "o", $strResult);
$strResult = str_ireplace("ó", "o", $strResult);
$strResult = str_ireplace("ù", "u", $strResult);
$strResult = str_ireplace("ú", "u", $strResult);
$strResult = str_ireplace("ç", "c", $strResult);
$strResult = str_ireplace("ö", "o", $strResult);
$strResult = str_ireplace("û", "u", $strResult);
$strResult = str_ireplace("ê", "e", $strResult);
$strResult = str_ireplace("ü", "u", $strResult);
$strResult = str_ireplace("ë", "e", $strResult);
$strResult = str_ireplace("ä", "a", $strResult);
$strResult = str_ireplace("'", " ", $strResult);
$strResult = preg_replace('/[^A-Za-z0-9 ]/', "", $strResult);
$strResult = trim($strResult);
$strResult = preg_replace('/[ ]{2,}/', " ", $strResult);
$strResult = str_replace(" ", "-", $strResult);
return $strResult;
}
In questo modo la creazione del nostro link sarà molto semplice:
//lettura dei valori dal database echo '<a href="prodotto' . $id . '/' . CleanString($nomeProdotto) . '">' . $nomeProdotto . '</a>';
Scriviamo la regola di rewrite url
A questo punto possiamo procedere con l’implementazione della regola di rewrite in questo modo:
RewriteEngine On RewriteRule ^prodotto([0-9]+)/([a-zA-Z0-9-]+)$ prodotti.php?id=$1
Questa regola stabilisce che: Quando trovi la stringa prodotto seguita da un numero di una o più cifre, seguita da “/”, seguita da una stringa alfanumerica (che può contenere il carattere “-”) di uno o più caratteri, richiedi la pagina prodotti.php?id=ilNumeroCheHaiTrovatoNellaPrimaSottostringa.
La seconda sottostringa non ci interessa in quanto disponiamo già dell’id che servirà a caricare i dettagli del prodotto, ma interesserà invece l’ottimizzazione per i motori di ricerca, per i quali sarà così disponibile, già a livello di url, il nome del prodotto.
Conclusione
Abbiamo visto tre esempi basilari di come implementare la riscrittura degli url. Teoricamente non vi sono limiti alle possibilità offerte da questo modulo di Apache se non nella conoscenza che abbiamo delle espressioni regolari. Infatti, come hai visto, si tratta in gran parte di questo.
E tu, utilizzi questa tecnica per migliorare l’indicalizzazione dei tuoi siti?
26 commenti
Trackback e pingback
-
Tweets that mention Il mod_rewrite e la magia di riscrivere gli URL (seconda parte) | Your Inspiration Web -- Topsy.com
[...] This post was mentioned on Twitter by yesWEBcan and Your Inspiration Web, mtx_maurizio. mtx_maurizio said: RT @YIW Il mod_rewrite ...





Bravo Maurizio!
io non utilizzo l’id del prodotto dell’url perché mi è stato detto da esperti SEO che i motori non digeriscono molto bene gli id.
per un catalogo utilizzo uno schema del genere /it/prodotti/prima-categoria/seconda-categoria/ultima-categoria/prodotto/ come alberatura “massima”.
Come esprssione regolare utilizzo sempre quella dell’altra volta.
Se un catalogo ha una struttura differente elimino qualche livello.
Ciao Luca.
io non utilizzo l’id del prodotto dell’url perché mi è stato detto da esperti SEO che i motori non digeriscono molto bene gli id.
Quello che non digeriscono bene sono le querystring, in particolare se lunghe. In questo esempio l’id viene fatto passare come “numero del prodotto” ed ovviamente non in forma di querystring.
Il passare anche le categorie nell’url è un’altra cosa positiva dal punto di vista dell’indicalizzazione.
io non mettendo l’id del prodotto faccio l’operazione inversa sul nome del prodotto, avendo un campo url (che è univico) nel DB e quindi faccio una select del tipo:
SELECT id, colonna
FROM prodotti
WHERE active = 1
AND url = ‘tosa-erba-elettrico-grande’
AND quello che vuoi tu
e dopo faccio tutte le operazioni che mi servono in PHP.
Se invece ho prodotto/tosa-erba/tosa-erba-elettrico-grande
Prima mi pesco l’id della categoria con un procedimento simile e quindi:
SELECT id
FROM categorie
WHERE active = 1
AND url = ‘tosa-erba’
AND quello_che_ti_serve
e poi la query di prima diventa:
SELECT id, colonna
FROM prodotti
WHERE active = 1
AND url = ‘tosa-erba-elettrico-grande’
AND categoria = categoria.id
AND quello che vuoi tu
Sicuramente avere le categorie è molto più utile per l’indicizzazione perché dici esattamente ai motori quello che c’è in quella pagina e ti aumenta il SERP.
Luca
Ciao, con tutte le query che fai rischi di rallentare il tutto e questo a google non piace ;) Inutile ammazzarsi per non mettere un id e poi fare 2 query inutili.
Non puoi avere 2 prodotti con lo stesso nome? Mi sembra assurdo. (In questo caso sono prodotti, ma potrebbe essere qualsiasi cosa)
Certo, e constato che questo approccio è sempre più diffuso.
Personalmente, sapendo come funziona MySql, ritengo che vi sia una differenza tra l’utilizzare un campo qualunque come dato univoco piuttosto che un campo indice, in particolare se si tratta di una chiave primaria. Vi sono differenze tecniche non solo nell’ambito delle prestazioni.
Grande articolo!
Un informazione: Il sistema wordpress funziona diversamente? Perchè trovo solo
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
Dipende dall’impostazione dei permalink.
Poi, di preciso, come lo fa posso solo immaginarlo in quanto non ho purtroppo anchra avuto tempo di smontare WP.
Probabilmente wordpress rileva l’indirizzo di richiesta (tramite qualcosa come $_SERVER[REQUEST_URI]) e lo processa direttamente per intero.
Si, uso un sistema molto simile. Le mie url sono di solito del tipo /sito-lingua/collezione/id%20testo. Non mi preoccupo di lettere accentate, simboli o spazi: passo tutto a rawurlencode, in questo modo le mie url supportano tranquillamente anche titoli in cirillico. Il testo che segue l’id è confrontato rigenerando l’url: se è diversa, restituisco 301 per far contenti i motori di ricerca che vedranno che sono un bravo ragazzo che unifica le url …
Cosa non si fa per far contenti i motori di ricerca… qualcuno darebbe anche un rene :-)
Volevo complimentarmi per i due articoli sul mod_rewrite: molto chiari e comprensibili.
Grazie Francesco :-)
WordPress implementa la logica nei file .php e non nel .htaccess “semplicemente” perchè permette di impostare modi differenti per riscrivere un url.. Diversamente conviene a mio avviso perdere un po’ più tempo nella creazione di una regola all’interno dell’htaccess che discrimini in base alla tipologia di url…
ad esempio: se l’url che punta a un prodotto è:
nomesito.com/id_numerico_prodotto/quello_che__voglio/
mentre quello per le categorie è :
nomesito.com/nome_categoria/quello_che_voglio/..
creereri due regole che passano allo stesso index.php una query string diversa; nel caso 1 index.php?id_prod=$1
e nel caso 2 index.php?id_cat=$1
In questo modo si allegerisce il compito di php che diversamente dovrebbe spulciarsi il db con diverse query (nel caso in cui nell’url nno sia specificata la chiave primaria, come suggeriva Maurizio). In questo modo invece sarà sufficente un isset($_GET[''id_cat']) per capire cosa mostrare ;-)
Salve Maurizio, sapresti spiegarmi come fa wordpress a creare la direttiva di questo tipo?
http://www.nomesito.it/?dove-siamo
mi piacerebbe molto emularla all’interno del mio CMS, ma non sono mai riuscito a ricrearla. Puoi darmi qualche spunto? grazie
Ciao Marco.
All’inizio dell’articolo spiego come WP implementa il sistema dei permalink. Come ho avuto modo di dire, secondo me è meglio passare anche l’id ed utilizzare il titolo “normalizzato” solo a beneficio dei motori di ricerca.
Se vuoi comunque emulare il sitema di WP, dovrai considerare che il titolo dell’articolo/pagina, dovrà essere un dato univoco; quindi dovrai procedere a dei controlli.
Ciao, bel post. Io non capisco molto di rewrite e dovrei riscrivere gli spazi di alcune url (ho varie url con alcuni spazi tra una parola e l’altra).
Ho provato a fare un redirect ma non ottengo risultati in alcun modo e così ho pensato che se magari prima riscrivo la url non otterrò alcun errore.
Ma se invece di fare tutti quei passaggi all’inizio della funzione non è più semplice fare un foreach su un array contenente tutte le modifiche?
Si, certo, é un’altra soluzione.
Ciao,
io non riesco a capire perchè facendo con il metodo delle cartelle da te descritto quando vado ad aprire il link non mi ritrova immagini e css e nell’url mi riporta anche la cartella,invece di riferirsi alla root come scritto nella regola dell’htaccess.
Ho fatto moltissime prove,ma non c’è verso di dire a quel link che si riferisce ad un file che si trova nella root.
Ciao
Grazie
Molto bene!
Ma in caso di cambio dominio e volessimo reindirizzare le vecchie pagine a quelle nuove, cosi da non perdere il PageRank, hai scritto qualcosa in merito?
Grazie
Ciao,
bello anzi bellissimo peccato che non funziona correttamente!!!
copiando il esattamente quello il codice sul post tutti i link hanno come suffisso “prodotto11″ quindi non funziona il css e tutte le immagini !!!
Sicuramente c’è qualche modifica da fare per far ritornare alla root principale.
In attesa di una soluzione, grazie comunque perché è ben fatto.
Potresti risolvere inserendo all’interno dell’head.
Tutti gli href successivi partono dalla base indicata attraverso questo tag.
Non so che implicazioni possa avere sui vari host, ad ogni modo in locale funziona.
Il tag che non ha preso è:
[pre][/pre]
Ciao,
articolo interessantissimo! Mi chiedevo se ai fini SEO conviene togliere anche articoli e preposizioni (purtroppo non ne so quasi niente ancora…).
Cioè meglio:
http://www.miosito.com/ricette/torta-all-arancia-di-nonna-teresa
oppure:
http://www.miosito.com/ricette/torta-arancia-nonna-teresa
?