In questo post vediamo cosa sono le regole di riscrittura degli url (rewrite rules) di WordPress e quali sono quelle predefinite già presenti nel cms.
Una volta capito il meccanismo di una singola regola vediamo come diventa più semplice inserirne di nostre.
Le funzioni che utilizzeremo sono degli alias di metodi della classe WP_rewrite.

Cosa significa riscrivere gli indirizzi

La riscrittura è un processo con cui vine deciso quale pagina deve essere mostrata asseconda dell’indirizzo digitato.
Per fare un semplice esempio, se in questo sito visitiamo la pagina

http://instileweb.com/articoli/wordpress

in realtà la pagina restituita è

http://instileweb.com/index.php?category_name=wordpress

cioè esiste una regola per cui qualsiasi parola che segua articoli/ deve essere riconosciuta come una categoria di post e quindi utilizzata per effettuare una query nel database. Nel nostro caso
viene visualizzato un elenco di tutti i post appartenenti alla categoria ‘wordpress’.

Benefici che derivano dalla riscrittura degli indirizzi

Sicuramente il fatto di eliminare i parametri get dall’URL rende più semplice l’orientamento nel sito e la memorizzazione dell’indirizzo da parte dei visitatori.
La riscrittura degli url può essere utilizzata per inserire parole chiave utili in ottica SEO.
Un altro caso in cui può essere utile è l’integrazione di uno script esterno al cms, alla logica degli indirizzi che abbiamo scelto per WordPress.

Un passo in dietro: il percorso di una richiesta.

Quando digitiamo un indirizzo nel browser stiamo facendo una richiesta al server per una particolare risorsa.
In base delle impostazioni dei permalink una richiesta può essere scritta in due modi

Con le query string

Indicando i vari parametri ad es. ?p=1 o ?category=wordpress
È la forma predefinita che troviamo appena installato wordpress. I Vari parametri servono per effettuare una query al database.

Con una forma leggibile

Del tipo /slug-articolo. Questa forma deve essere attivata in impostazioni>permalink.

impostazioni-permalink-wordpress

Apparentemente visitando l’indirizzo miosito.it/ciao-mondo sembra che stiamo andando alla ricerca della cartella /ciao-mondo del server.
In realtà quando attiviamo i permalink personalizzati viene creato un file .htaccess che modifica questo comportamento.

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wprewitest/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wprewitest/index.php [L]
</IfModule>
# END WordPress

Tutte le volte che effettuiamo la ricerca di una cartella o di un file che non esistono sul server, la richiesta viene dirottata al file index.php e trattata diversamente.
Semplificando possiamo dire che la forma più leggibile viene convertita nella forma a query string dove i parametri sono ricavati in base a delle regole preimpostate o scritte da noi.

Le regole di riscrittura degli url: rewrite rules

Le rewrite rules sono in una nuova installazione di WordPress sono circa settanta. Per avere una lista completa delle regole è possibile interrogare il database o effettuare un print_r dell’oggetto $wp_rewrite.

Rewrite rules nel database

SELECT *
FROM wp_options
WHERE option_name = 'rewrite_rules'

rewrite-rules-database-wp-options
Le regole sono tutte all’interno di option_value.

Rewrite rules nell’oggetto $wp_rewrite

//functions.php
add_action( 'template_redirect', 'isw_stampa_rules' );
function isw_stampa_rules()
{
    global $wp_rewrite;
    echo '<pre>';
    print_r( $wp_rewrite->rules );
     echo '</pre>';
     die();
}

Risultato del print_r.

print_r-rewrite-rules

Significato di una regola

Prendiamo ad esempio la quarta regola:

[category/(.+?)/?$] => index.php?category_name=$matches[1]

Vediamo che è composta da due parti come una coppia chiave / valore di un array.
La prima parte non è altro che uno schema di url che contiene una parte fissa (category) e una parte variabile (.+?) indicata come espressione regolare. Quest’ultima può essere una sequenza di qualsiasi carattere escluso l’a capo

[category/(.+?)/?$]

Tutte le volte che WordPress riconosce questo pattern lo interpreta come se fosse la seconda parte della regola dove al posto di $matches[1] viene inserita la parte variabile dell’URL.

index.php?category_name=$matches[1]

In pratica se digitiamo http://miodomionio.it/category/css in realtà viene caricata la pagina http://miodomionio.it/?category_name=css con tutti gli articolo appartenenti alla categoria css.

Altri esempi di rewrite rules predefinite

Archivi in base alla data.

 [([0-9]{4})/([0-9]{1,2})/?$] => index.php?year=$matches[1]&monthnum=$matches[2]

Nel pattern vergono riconosciuti anno e mese
http://dominio.it/2014/5

Feed di un archivio in base alla data.

[([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/feed/(feed|rdf|rss|rss2|atom)/?$]

I seguenti indirizzi rientrano nel modello
/2014/10/5/feed
/2014/10/05/feed/feed
/2014/10/5/feed/rss
/2014/10/05/feed/atom ecc..

Cosa succede se aggiungiamo un custom post type?

Creiamo un nuovo tipo di post personalizzato chiamato recensione.

//functions.php
add_action( 'init', 'isw_crea_post_type' );
function isw_crea_post_type()
{
  register_post_type( 'isw_recensione',
    array(
      'labels' => array(
        'name' => __( 'Recensioni' ),
        'singular_name' => __( 'Recensione' )
      ),
      'public' => true,
      'has_archive' => true,
    )
  );
}

Effettuiamo nuovamente un print_r di $wp_rewrite->rules. Inizialmente sembra che non sia cambiato nulla rispetto alla situazione iniziale. Se invece visitiamo la pagina impostazioni>permalink anche senza salvare e poi lanciamo di nuovo print_r( $wp_rewrite->rules ); vediamo che sono state aggiunte 20 nuove regole.

    [isw_recensione/?$] => index.php?post_type=isw_recensione
    [isw_recensione/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?post_type=isw_recensione&feed=$matches[1]
    [isw_recensione/(feed|rdf|rss|rss2|atom)/?$] => index.php?post_type=isw_recensione&feed=$matches[1]
    [isw_recensione/page/([0-9]{1,})/?$] => index.php?post_type=isw_recensione&paged=$matches[1]

    [ ... ]

Flush delle rewrite rules

Ogni volta che effettuiamo una modifica in php che riguarda le regole di riscrittura degli URL bisogna assicurarsi che la lista sia aggiornata nel database. È possibile aggiornare le regole in due modi.
1) Visitando la pagina impostazioni>permalink
2) Direttamente in php utilizzando la funzione

flush_rewrite_rules();

flush_rewrite_rules(); deve essere lanciata una volta sola, quando necessario, e non a ogni caricamento di pagina. Hook adatti a cui registrare la funzione possono essere quelli di attivazione o di disattivazione dei plugin.

Aggiungere regole di riscrittura degli url

Per specificare regole di riscrittura addizionali è possibile utilizzare la funzione add_rewrite_rule($regex, $redirect, $after);

Parametri

$regex l’espressione regolare che viene confrontata con l’URL inserito nel browser.
$redirect l’url che vogliamo venga caricato una volta che viene trovata corrispondenza tra url inserito e il pattern di $regex.
$after Può essere ‘top’ o ‘bottom’. Indica la posizione della nuova regola nella lista.

Vediamo un esempio:

Creiamo una regola per cui un url del tipo
http://miosito.it/biblioteca/dante/la-divina-commedia
viene interpretato come
?page_id=4&autore=dante&titolo=divina-commedia

add_action( 'init', 'isw_add_rules' );
function isw_add_rules()
{
add_rewrite_rule(
	'^biblioteca/([^/]*)/([^/]*)/?',
	'index.php?page_id=4&autore=$matches[1]&titolo=$matches[2]',
	'top');
}

Il codice dell’esempio in questo modo non funzionerebbe inquanto le query var autore e titolo non esistono su WordPress.

Espandere l’elenco delle query var

Le query var sono le variabili autorizzate che possono corrispondere a particolari pattern negli url. Queste vengono poi utilizzate per effettuare una query al database.

La lista completa delle query var è definita nell’oggetto $wp_query.

add_action( 'template_redirect', 'isw_stampa_query' );
function isw_stampa_query()
{

     global $wp_query;
     echo '<pre>';
     print_r($wp_query);
     echo '</pre>';
     die();
}

Ad esempio se visitiamo la ‘pagina di esempio‘ di una nuova installazione di WordPress vediamo tutto l’elenco delle variabili autorizzata. Possiamo notare che alcune di queste sono impostate, in particolare [pagename] e [name]

    [query_vars] => Array
        (
            [page] => 0
            [pagename] => pagina-di-esempio
            [error] =>
            [m] =>
            [p] => 0
            [post_parent] =>
            [subpost] =>
            [subpost_id] =>
            [attachment] =>
            [attachment_id] => 0
            [name] => pagina-di-esempio
            [static] =>
            [page_id] => 0
            [second] =>
            [minute] =>
            [hour] =>
            [day] => 0
            [monthnum] => 0
            [year] => 0
            [w] => 0
            [category_name] =>
            [tag] =>
            [cat] =>
            [tag_id] =>
            [author] =>
            [author_name] =>
            [feed] =>
            [tb] =>
            [paged] => 0
            [comments_popup] =>
            [meta_key] =>
            [meta_value] =>
            [preview] =>
            [s] =>
            [sentence] =>
            [fields] =>
            [menu_order] =>
            [category__in] =>

Per aggiungere nuove query var, quindi registrare nuove variabili get/post usiamo la funzione add_rewrite_tag().

Riprendiamo l’esempio della biblioteca e aggiungiamo nuove query vars.

add_action( 'init', 'isw_add_rules' );
function isw_add_rules()
{

add_rewrite_rule(
	'^biblioteca/([^/]*)/([^/]*)/?',
	'index.php?page_id=4&autore=$matches[1]&titolo=$matches[2]',
	'top');
add_rewrite_tag('%autore%','([^&]+)');
add_rewrite_tag('%titolo%','([^&]+)');

//flush_rewrite_rules();
}

A questo punto visitando la pagina http://miosito.it/biblioteca/dante/la-divina-commedia
effettuando print_r($wp_query); otteniamo.

WP_Query Object
(
    [query] => Array
        (
            [page_id] => 4
            [autore] => dante
            [titolo] => divina-commedia
        )

    [query_vars] => Array
        (
            [page_id] => 4
            [autore] => dante
            [titolo] => divina-commedia
            [error] =>
          [...]

Creiamo un template di pagina per la biblioteca

Creiamo un file biblioteca.php

/*
Template Name: Template biblioteca
*/

$autore = get_query_var( 'autore' );
$titolo = get_query_var( 'titolo' );

echo  $titolo . '</br>';
echo  $autore;

Colleghiamo la pagina ‘Biblioteca’ (id = 4) di WordPress con il template di pagina.
template-pagina-biblioteca

Visitando la pagina http://miodominio.it/dante/divina-commedia dovremmo vedere stampati a monitor autore e titolo, i quali sono stati ricavati utilizzando la funzione get_query_var();

A questo punto siamo in grado di collegare un eventuale script indipendente da WordPress che asseconda dei valori di autore e titolo genera una pagina diversa.

Plugin utili

Esistono diversi plugin nel repository di WordPress che riguardano le rewrite rules.

Abbiamo testato Rewrite Rules Inspector.

Rewrite Rules Inspector

rewrite-rules-inspector

Una volta installato lo troviamo sotto strumenti>rewrite rules
strumenti-rewrite-rules

Accediamo a una schermata con elenco di tutte le regole.

elenco-rewrite-rules

Abbiamo la possibilità di effettuare un flush delle regole o scaricare un file di testo con tutto l’elenco.

flush-download-rules

Ma la funzionalità più importante è quella che ci permette di testare la corrispondenza di url che inseriamo con una o più regole registrate.

corrispondenza-url-regole-rewrite

Conclusioni

In questo articolo abbiamo visto come WordPress fornisca un sistema interno per gestire la riscrittura degli indirizzi. Questo sistema che usa una sintassi simile a quello del mod_rewrite di apache, ci permette di lavorare direttamente in php piuttosto che intervenire sul file .htaccess.


  inStileWeb.com
blog comments powered by Disqus