§ 27. Breadcrumbs: lo script universale in PHP

Sono sicuro che i lettori del presente paragrafo sanno già che cosa sia e quanto sia utile il menu breadcrumbs: ne avevo scritto pure io. Quindi ora vedo di proporre una prima soluzione, un primo consiglio pratico sul come creare un menu breadcrumbs con uno script in PHP. Per questa volta si tratta di una soluzione universale – generica – adatta per dei progetti di piccole dimensioni e con una struttura non particolarmente complessa, compresi gli eventuali siti costruiti senza un CMS e/o, addirittura, senza un database.
Le persone più pigre possono andare direttamente al codice finale completo, mentre io inizierei dalla spiegazione di alcuni dettagli: la comprensione di questi vi aiuterà a ottimizzare il risultato finale per le vostre esigenze concrete.
1. Elaboriamo l’algoritmo
I siti web moderni progettati in un modo intelligente hanno gli URL strutturati sulla base della gerarchia delle pagine: l’indirizzo di ogni singola pagina concreta contiene i riferimenti a ognuna delle pagine di rango superiore (le quali svolgono spesso la funzione delle categorie); ogni singolo riferimento è separato dagli slash («/») dal resto dell’indirizzo. In qualità di un semplice esempio possiamo vedere l’URL del presente paragrafo: https://eugigufo.net/it/inerario/paragrafo27.
Questo indirizzo, infatti, è fatto dalle seguenti componenti:
1. La pagina iniziale (eugigufo.net, la root),
2. La pagina iniziale della versione italiana del sito (it),
3. L’indice dell’Inerario (inerario),
4. L’oggetto della categoria, in questo specifico caso il paragrafo 27 (paragrafo27).
In sostanza, durante la navigazione del visitatore dalla pagina iniziale verso questo paragrafo, l’URL a egli visibile si arricchisce di nuovi elementi: quelli che indicano i livelli gerarchici precedenti e quello della pagina corrente. Di conseguenza, possiamo facilmente immaginare l’algoritmo della costruzione del menu breadcrumbs da tradurre in codice:
1. Ottenere l’URL della pagina corrente,
2. Analizzare l’URL ottenuto, scomponendolo in elementi separati dai slash,
3. Per ogni elemento identificato assegnare un nome (che verrà linkato e visualizzato nel menu) e costruire il suo indirizzo,
4. Trasmettere i nomi e gli indirizzi in un array che poi verrà utilizzato nel template del menu breadcrumbs,
5. Organizzare la visualizzazione del template del menu breadcrumbs sulle pagine del sito.
Tale algoritmo non dipende dal modo in cui è stato realizzato il sito (e quindi non dipende dal tipo e dal solo fatto di esistenza di un CMS) in quanto per funzionare ha bisogno solo dell’URL della pagina corrente. Non è nemmeno necessario interrogare un eventuale database per ottenere i nomi delle pagine superiori.
2. Ipotizziamo un caso realistico
Supponiamo di voler aggiungere il menu breadcrumbs a un piccolo sito aziendale che si trova all’indirizzo codicephp.it.
Supponiamo anche che quel sito abbia la seguente struttura:

Il nome della pagina    L’indirizzo della pagina
Home    codicephp.it/
Chi siamo    codicephp.it/aboutus
Servizi    codicephp.it/services
   Portfolio    codicephp.it/services/portfolio
   Prezzi    codicephp.it/services/prices
Blog    codicephp.it/services/blog
Contatti    codicephp.it/contacts

In particolare, le pagine Portfolio e Prezzi ci servono per verificare il funzionamento del nostro menu breadcrumbs con più di una voce (quindi con qualcosa oltre il link alla Home). Il nostro obbiettivo è quello di far comparire il menu breadcrumbs in questo header:

Ora, finalmente, possiamo dedicarci al codice. Esso sarà composto da due parti: una parte responsabile della formazione dell’array contenente i nomi assegnati agli elementi dell’URL e i rispettivi indirizzi (quindi i nomi e gli URL delle pagine di rango superiore a quella corrente) e l’altra parte responsabile della visualizzazione del menu breadcrumbs.
Ovviamente, anche la prima parte del codice deve in qualche modo essere presente su tutte le pagine del sito perché dobbiamo analizzare l’URL corrente ogni volta che visualizziamo il menu breadcrumbs: per esempio, potete inserirla/includerla nel header.
3. La formazione dell’array dei breadcrumbs
Prima di tutto, seguendo il nostro algoritmo, dobbiamo determinare l’URL della pagina corrente. A tale scopo ci è molto utile la variabile superglobale $_SERVER offertaci dal PHP: in essa sono contenute le varie informazioni sullo script eseguito sul lato server. L’URL corrente è raggiungibile grazie al REQUEST_URI:

$cur_url = $_SERVER['REQUEST_URI'];

Una volta recuperato l’URL, dobbiamo scomporlo in elementi. Non è difficile, dato che tutti i suoi elementi sono separati dai slash, quindi analizziamo l’URL corrente:

$urls = explode('/', $cur_url);

Procediamo a creare un array vuoto per metterci dentro le informazioni sui nomi degli elementi dei breadcrumbs e dei loro indirizzi:

$crumbs = array();

Il prossimo passaggio dell’algoritmo è la formazione dei link e dei nomi degli elementi del menu. A tale scopo analizziamo le parti dell’URL corrente all’interno di un ciclo, creando anche un array per gli indirizzi degli elementi dei breadcrumbs che rappresentano le pagine precedenti.
Trovo logico creare il menu breadcrumbs per tutte le pagine del sito a eccezione della prima (la home o la principale: dipende come preferite chiamarla). Infatti, non avrebbe senso generare un menu con un solo link che per di più ci porterebbe alla medesima pagina corrente.
Quindi ci viene un codice di questo tipo:

if (!empty($urls) && $cur_url != '/') {
   foreach ($urls as $key => $value) {
      $prev_urls = array();
   }
}

Ora dobbiamo riempire l’array degli indirizzi dei singoli elementi del futuro menu breadcrumbs. A tale scopo aggiungiamo al nostro ciclo un altro ciclo, il quale verrà eseguito per ogni elemento dell’URL della pagina corrente:

for ($i = 0; $i <= $key; $i++) {
    $prev_urls[] = $urls[$i];
}

Come si vede dal codice, per l’elemento corrente con la chiave $key verranno registrati all’array $prev_urls gli indirizzi di tutte le parti precedenti contenute nell’URL della pagina corrente.
In questa fase gli indirizzi degli oggetti (pagine) precedenti costituiscono gli elementi dell’array $prev_urls. Per assemblare un URL completo della pagina precedente bisogna unire con gli slash gli elementi dell’array.
Evitiamo di creare un URL per l’elemento dell’array che corrisponde all’identificatore della pagina corrente. Quindi aggiungiamo al ciclo interno il seguente codice:

if ($key == count($urls) - 1)
{
    $crumbs[$key]['url'] = '';
}
elseif (!empty($prev_urls))
{
    $crumbs[$key]['url'] = count($prev_urls) > 1 ? implode('/', $prev_urls) : '/';
}

In questa fase il nostro array finale $crumbs contiene gli indirizzi degli elementi superiori – dal punto di vista gerarchico – rispetto alla pagina corrente. Per esempio, per la pagina «Portfolio» del nostro sito immaginario l’array $crumbs avrà il seguente aspetto:

Array (
 
    [0] => Array (
        [url] => /
    )
 
    [1] => Array (
        [url] => /services
    )
 
    [2] => Array (
        [url] =>
    )
 
)

A questo punto, l’unica cosa che ci manca sono i nomi delle voci del menu breadcrumbs. Per crearli, aggiungiamo al ciclo interno (dopo la formazione degli indirizzi degli elementi) il riempimento dell’array $prev_urls con i nomi:

switch ($value) {
    case 'about' : $crumbs[$key]['text'] = 'Chi siamo';
        break;
 
    case 'services' : $crumbs[$key]['text'] = 'Servizi';
        break;
 
    case 'blog' : $crumbs[$key]['text'] = 'Blog';
        break;
 
    case 'contacts' : $crumbs[$key]['text'] = 'Contatti';
        break;
 
    case 'portfolio' : $crumbs[$key]['text'] = 'Portfolio';
        break;
 
    case 'prices' : $crumbs[$key]['text'] = 'Prezzi';
        break;
 
    default : $crumbs[$key]['text'] = 'Home';
        break;
}

Come potete vedere da questo ultimo codice, a ogni elemento dei breadcrumbs il nome viene assegnato in base all’URL della rispettiva pagina. Certamente, l’assegnazione manuale dei nomi non è la soluzione migliore. Tale soluzione potrebbe essere accettabile solo per dei piccoli siti con poche pagine o quando non c’è proprio la possibilità di sfruttare un database e/o il CMS del sito per la creazione automatica degli elementi del menu breadcrumbs.
Per il nostro metodo attualmente studiato siamo riusciti, comunque, a ottenere un array con i dati necessari. Per la pagina «Portfolio», per esempio, l’array avrà il seguente aspetto:

Array(
 
    [0] => Array (
        [url] => /
         => Home
    )
 
    [1] => Array (
        [url] => /services
         => Servizi
    )
 
    [2] => Array (
        [url] =>
         => Portfolio
    )
 
)

Ci rimane solo far visualizzare il nostro menu breadcrumbs sulle pagine del sito.
4. Visualizzare il menu breadcrumbs sulle pagine del sito
Il nostro obiettivo iniziale dichiarato è stato quello di proporre una soluzione universale. Di conseguenza, anche la visualizzazione del menu breadcrumbs appena descritto deve funzionare su qualsiasi sito. La facciamo con un altro script in PHP che poi dovrà essere inserito nel codice delle pagine del sito.
Prima di tutto vi ricordo di creare un DIV, all’interno del quale mettere il codice PHP che stiamo per scrivere. L’aspetto estetico del menu potrà essere impostato con il vostro file di stili CSS.

<div class="menubreadcrumbs">
    <!--Al posto di questo commento va messo il codice PHP della visualizzazione del menu breadcrumbs-->
</div>

Il menu stesso può essere creato, per esempio, sotto forma di un elenco contenuto tra i tag <ul>. I dati saranno estratti dall’array all’interno di un ciclo, quindi nel DIV del menu scriviamo:

<?php if (!empty($crumbs)) { ?>
    <ul class="breadcrumb">
        <?php foreach ($crumbs as $item) { ?>
            <?php if (isset($item)) { ?>
                <li>
                    <a href="<?php echo $item['url'] ?>"><?php echo $item['text'] ?></a>
                </li>
            <?php } ?>
        <?php } ?>
    </ul>
<?php } ?>

Come potete vedere dal codice, ogni elemento dell’array con i breadcrumbs viene visualizzato come un link, dove il relativo URL proviene dall’elemento con l’indice «url», mentre il nome della voce relativa proviene dall’elemento con l’indice «text». Il risultato è questo:

È quasi quello che ci aspettavamo. «Quasi» perché l’ultima voce del menu è il link «vuoto» (privo di un URL) alla pagina corrente. Una cosa del genere non ha molto senso, quindi proviamo a trasformare l’elemento senza un URL (non ce l’ha perché siamo stati noi a decidere così) in un semplice testo. Quindi inseriamo nel nostro ciclo di visualizzazione la seguente verifica:

<?php if (!empty($item['url'])) { ?>
    <a href="<?php echo $item['url'] ?>"><?php echo $item['text'] ?></a>
<?php } else { ?>
    <?php echo $item['text'] ?>
<?php } ?>

Ora il nostro menu breadcrumbs ha un aspetto molto più bello e logico:

Quindi possiamo considerare concluso il lavoro.
5. Il codice completo dello script
Il codice PHP che crea l’array con gli elementi del menu breadcrumbs è dunque il seguente:

$cur_url = $_SERVER['REQUEST_URI'];
$urls = explode('/', $cur_url);
 
$crumbs = array();
 
if (!empty($urls) && $cur_url != '/') {
    foreach ($urls as $key => $value) {
        $prev_urls = array();
        for ($i = 0; $i <= $key; $i++) {
            $prev_urls[] = $urls[$i];
        }
        if ($key == count($urls) - 1)
            $crumbs[$key]['url'] = '';
        elseif (!empty($prev_urls))
            $crumbs[$key]['url'] = count($prev_urls) > 1 ? implode('/', $prev_urls) : '/';
 
        switch ($value) {
            case 'about' : $crumbs[$key]['text'] = 'Chi siamo';
                break;
            case 'services' : $crumbs[$key]['text'] = 'Servizi';
                break;
            case 'blog' : $crumbs[$key]['text'] = 'Blog';
                break;
            case 'contacts' : $crumbs[$key]['text'] = 'Contatti';
                break;
            case 'portfolio' : $crumbs[$key]['text'] = 'Portfolio';
                break;
            case 'prices' : $crumbs[$key]['text'] = 'Prezzi';
                break;
            default : $crumbs[$key]['text'] = 'Home';
                break;
        }
    }
}

Il codice PHP che visualizza il menu breadcrumbs è invece il seguente:

<?php if (!empty($crumbs)) { ?>
    <ul class="breadcrumb">
        <?php foreach ($crumbs as $item) { ?>
            <?php if (isset($item)) { ?>
                <li>
                    <?php if (!empty($item['url'])) { ?>
                        <a href="<?php echo $item['url'] ?>"><?php echo $item['text'] ?></a>
                    <?php } else { ?>
                        <?php echo $item['text'] ?>
                    <?php } ?>
                </li>
            <?php } ?>
        <?php } ?>
    </ul>
<?php } ?>

Mentre il codice CSS deve essere scritto da voi in base all’aspetto grafico del vostro sito.
Oltre al CSS, l’unica cosa che vi resta da fare è sostituire gli identificatori degli indirizzi e dei relativi nomi con quelli del sito sul quale intendete utilizzare lo script.
6. Le osservazioni finali
Come potete facilmente notare, lo script del menu breadcrumbs descritto in questo paragrafo è estremamente primitivo. Lo è, prima di tutto, a causa del suo carattere universale: perseguendo l’obbiettivo di farlo funzionare con qualsiasi tipo di progetto, l’ho reso indipendente da tutte le possibili particolarità dei numerosi CMS esistenti e ho fatto in modo che funzioni anche sui siti costruiti senza un CMS. È proprio per questo che il menu non viene generato in un modo del tutto automatico. Allo stesso tempo, lo script permette allo sviluppatore di un sito di non inserire manualmente tanti link uguali (modificandoli ogni qualvolta una pagina cambi la propria posizione nella gerarchia del sito), ma scrivere i loro dati una sola volta: nello script, appunto.
Nel prossimo paragrafo scriverò di un caso molto più complesso e interessante: la creazione del menu breadcrumbs per un sito sviluppato con il WordPress. Sfruttando il database di un sito del genere sarà possibile creare uno script completamente autonomo in tutti i suoi aspetti. Una volta caricato sul sito, non dovrà più essere toccato, nemmeno dopo l’aggiunta delle nuove pagine al sito stesso.