Una caratteristica comune della maggior parte dei siti web, siano essi statici o dinamici, è la centralizzazione della gestione dell'header e del footer all'interno di specifiche risorse. Il vantaggio è evidente. Se le nostre pagine presentano uno struttura come questa
- inclusione dell'header
- contenuto specifico della pagina
- inclusione del footer
avremo la sicurezza che tutte le pagine condividono lo stesso aspetto, gli eventuali loghi o banner e le informazioni comuni ad ogni pagina, come ad esempio menù di navigazione, recapiti, aiuto on line.
Ovviamente ciò significa che tutti gli aspetti condivisi (ovvero loghi, menù, recapiti ecc...) vanno inserite nell'header o nel footer. Il principio vale qualsiasi sia la tecnologia o il linguaggio di programmazione adottato dal sito. Anche lavorando in HTML possiamo realizzare questa architettura delegando al Web Server il compito di includere le risorse condivise. Un esempio di questo tipo è la direttiva virtual include di Apache, che permette di inserire la risorse condivise al momento di servire la pagina, mediante un comando del tipo
<!--#include virtual="/header.html" -->
Per ulteriori informazioni su questo modo di lavorare rimandiamo alla documentazione di Apache.
Nel caso di PHP, l'implementazione della tecnica potrebbe essere
include '../include/header.php' ;
… contenuto della pagina (HTML, PHP o altro) …
include '../include/footer.php' ;
Dove la pagina header.php
si occupa di definire l'aspetto generale del sito, caricare gli eventuali JavaScript e/o fogli di stile, inizializzare la sessione ed includere altre eventuali risorse condivise da tutte le pagine. Quest'architettura presenta notevoli vantaggi ed è molto popolare. Lavorando con PHP esiste però un possibile problema. Se dobbiamo autenticare gli utenti, avremo una pagina di login e una pagina di autenticazione (detta anche controller). Siccome tutte le pagine devono includere la header.php
, potrebbe verificarsi la seguente situazione
- La pagina di login inoltra l'azione al controller (o pagina di autenticazione)
- Il controller, come tutte le pagine, inizia includendo la
header.php
- Dopo aver validato l'utente il controller potrebbe caricare la homedel sito. Questo solitamente viene fatto in due modi (a seconda dell'architettura del sito):a) L'azione viene inoltrata alla pagina homeb) Il controller include la pagina home
Nel secondo scenario (caso b) si verifica un errore. L'header.php
è stato già incluso dal controller, poiché è necessario inizializzare la sessione prima di memorizzare il risultato dell'autenticazione (ad esempio in una variabile di sessione). Quando includiamo la pagina home, che a sua volta deve includere la header.php
, l'interprete PHP segnala un errore come questo
Notice
: A session had already been started - ignoring session_start() in
C:\Home\Site\include\header.php
on line
16
non si tratta di errore bloccante, perché possiamo sempre mettere le mani al file php.ini
e nascondere questo tipo di messaggi all'utente, ma è comunque meglio evitare problemi.
Vediamo alcune soluzioni possibili:
- Implementare un controller discreto: significa scrivere il codice del controller in modo che non venga prodotto alcun output, né settata alcuna variabile di sessione. Un controller di questo tipo si limita a inoltrare (o includere) la pagina home passando una qualche variabile con l'esito dell'autenticazione: sarà poi la pagina home, o addirittura la
header.php
, che si incaricherà di memorizzare i dati dell'utente nella sessione. In questo modo il controller può fare a meno di includere l'header.php
e il problema non si verifica - Incaricare il controller di caricare ex-novo la pagina home, anziché includerla. Questo implica un passaggio in più, perché la sequenza di autenticazione diventa login → controller → home anziché login → home (via controller). Se il codice è scritto bene il passaggio in più non costa molto (in termini di performance) e potrebbe essere una buona scelta
- Definire una variabile nel controller che permetta all'
header.php
di sapere che stiamo caricando la home “arrivando” dall'autenticazione, ad esempio
// Codice da inserire nel controller
$fromLogin = true ;
...
// Codice da inserire nell'header
if (!isset($fromLogin)) {
// Gestione della sessione
}
Lo svantaggio di questa soluzione è che il controller dovrà contenere una copia del codice strettamente necessario al suo funzionamento, che dovrà essere copiato dall'header e incollato nel controller. Questo rende un po' laboriosa la manutenzione del sito, perché ogni modifica nel controller andrà riportata anche nell'header, e viceversa
- Implementare il controller in modo da includere una pagina di benvenuto, anziché la home del sito, che venga caricata solamente dopo il login. Tale pagina di benvenuto sarà l'unica a non includere l'header, perché si assume che venga caricata solamente dal controller. Lo svantaggio è che questa pagina non mostrerà all'utente le funzionalità abilitate dal suo account, perché queste sono gestite nell'header, che è stato caricato prima dell'autenticazione. E' quindi necessario re-indirizzare l'utente verso la home, mediante un link o dopo qualche istante.
Queste sono alcune delle soluzioni più semplici, a portata di tutti. Esistono soluzioni più raffinate che sfruttano, ad esempio, la potenzialità del DHTML (soprattutto JavaScript e jQuery) per "aggiustare le cose" dopo che la pagina è stata caricata, in modo da riflettere l'esito dell'avvenuta autenticazione dopo aver caricato la pagina. Trattandosi di codice eseguito lato client bisogna però evitare di aprire qualche falla di sicurezza, per cui l'argomento merita una trattazione a parte.