Sei sulla pagina 1di 137

Sviluppare plugin di WordPress

In questo articolo daremo una definizione quanto più chiara possibile di cosa sia un plugin di WordPress. Si tratta di una
precisazione importante per poter affrontare in modo completo il tema generale dei plugin per il noto Blog engine/CMS
Open Source.

Un plugin di WordPress è un componente che viene aggiunto a WordPress per modificarne o estenderne le funzionalità.

Un plugin viene spesso chiamato modulo in altre applicazioni simili, ma la definizione rimane nello specifico la medesima.
Lo scopo di un plugin è infatti quello di permettere agli utilizzatori di eseguire delle operazioni in modo diverso rispetto a
quello previsto da WordPress o di aggiungere nuove operazioni a quelle predefinite.

Un esempio del primo tipo di plugin è quello che aggiunge dei ruoli utente a WordPress oltre a quelli tradizionali, in tal caso
viene quindi migliorata una funzionalità già disponibile. Nello stesso modo un plugin che gestisce gli slideshow appartiene
al secondo tipo, poiché per il momento WordPress non consente nativamente tale operazione, viene quindi integrata una
nuova funzionalità.

I plugin vengono attivati o disattivati nella sezione amministrativa di WordPress. Quando un plugin viene attivato,
WordPress include tutto il suo codice nel suo intero flusso di esecuzione consentendo al plugin di operare sia nel frontend
che nel backend del sito (a meno che l’autore del plugin non opti per operare solo in uno di questi due contesti).

Al contrario, quando un plugin viene disattivato, WordPress lo rimuove dal suo flusso di esecuzione e si comporta come se
il plugin non esistesse, ossia il codice del plugin non viene più eseguito.

WordPress non assegna privilegi di esecuzione inferiori ai plugin: ciò significa che un plugin può di fatto apportare
qualsiasi tipo di modifica a WordPress. Da qui sorge il problema dei bug e delle vulnerabilità nei plugin: se un plugin ha
un problema, anche WordPress ha lo stesso problema e non di rado quest’ultimo riguarda la sicurezza.

Per questo motivo una delle procedure di risoluzione dei problemi in WordPress prevede appunto la disabilitazione dei
plugin al fine di individuare quello che è all’origine del problema (una falla, un malfunzionamento, un calo di prestazioni..).

Nonostante i plugin, secondo le intenzioni della community di WordPress, debbano essere rilasciati in modo libero e aperto
(seguendo i termini contenuti nella licenza GPL per le applicazioni Open Source), una cospicua fetta dei plugin presenti sul
mercato sono disponibili a pagamento.

Esiste una differenza di fondo tra i plugin a pagamento e quelli liberi e gratuiti presenti nella repository ufficiale di
WordPress, esso risiede sostanzialmente nel modo in cui i plugin vengono aggiornati.

Mentre i plugin della repository ufficiale di WordPress sono tutti aggiornabili in automatico (ovviamente se l’autore rilascia
con regolarità gli aggiornamenti), quelli a pagamento non sempre lo sono e quindi spesso si è costretti ad installare la nuova
versione manualmente.

Installare un plugin manualmente è un’operazione molto semplice: è sufficiente uploadare la catella del plugin con i suoi
file (dopo averli decompressi) nella directory /wp-content/plugins e quindi attivarlo nel backend di WordPress.

Come abbiamo appena sottolineato, l’aggiornamento di un plugin è un requisito essenziale per gestire al meglio WordPress.
Un plugin che non viene mai aggiornato non solo può causare problemi con gli aggiornamenti delle versioni di WordPress,
ma rappresentare esso stesso un potenziale problema di sicurezza.

Se infatti un plugin viene disattivato ma i suoi file non vengono cancellati, questi possono essere usati per attacchi remoti se
sono vulnerabili. Il problema della sicurezza, insieme a quello dell’usabilità, è una questione di primaria importanza per i
plugin di WordPress. Questi aspetti non vanno mai trascurati sia che si voglia scegliere un plugin e sia che si desideri
svilupparlo in modo autonomo.
Nella prossima lezione esamineremo la struttura del codice di un plugin di WordPress.

Struttura del codice di un plugin WordPress


In questo articolo vedremo come è strutturato un plugin di WordPress al suo interno. I plugin di WordPress seguono una
struttura predefinita solo per alcune parti, mentre per altre la scelta dipende dall’autore del plugin.

Prima di iniziare è bene ricordare che un plugin per essere attivato con successo non deve contenere errori di sintassi PHP.
In caso contrario il plugin non verrà attivato e WordPress mostrerà un messaggio contenente i dettagli dell’errore. Inoltre
quando si lavora con i plugin è sempre consigliabile abilitare la modalità di debug di WordPress nel file wp-config.php
impostando la costante WP_DEBUG su true.

Struttura  dei  file  e  delle  directory  

La pratica comunemente seguita e raccomandata è quella di dare al file principale del plugin lo stesso nome della directory
in cui sono contenuti i file del plugin. Quindi se la directory viene chiamata myplugin, il file principale del plugin verrà
nominato myplugin.php. Tuttavia, come vedremo in seguito, questo non basta ancora affinché WordPress includa un
plugin nell’elenco della sezione Plugin nel backend.

I plugin vanno inseriti nella directory wp-content/plugins. WordPress analizza il contenuto di questa directory ad
ogni sua inizializzazione. Quindi il percorso del nostro ipotetico plugin sarà wp-
content/plugins/myplugin/myplugin.php (come vedremo WordPress dispone di diverse funzioni e costanti
per far riferimento sia all’URL assoluto che al percorso dei plugin ).

Il file principale del plugin può di fatto contenere l’intero codice del plugin. Tuttavia questa soluzione si applica solo nel
caso di plugin molto semplici. Nel caso invece di plugin più complessi, il file principale del plugin servirà semplicemente a
caricare il codice del plugin che risiederà in file esterni che si troveranno sempre all’interno della directory principale del
plugin stesso.

Un plugin di solito non contiene solo file PHP, ma anche file CSS, JavaScript ed immagini. Queste risorse possono essere
utilizzate sia nel frontend che nel backend del sito, come ad esempio nel pannello di controllo del plugin (per le sue
impostazioni). La struttura delle directory aggiuntive e dei nomi dei file ausiliari di fatto non segue alcuno schema
predefinito, anche se la community di WordPress incoraggia gli autori di plugin ad usare una strutturazione coerente.

Il  file  principale  del  plugin  

Di fatto l’unico punto saldo nella struttura di un plugin è il suo file principale. WordPress riconosce un plugin come valido
se all’inizio di questo file è contenuto un blocco di commenti che ha la seguente struttura:

/*  
Plugin Name: My Plugin  
Version: 1.0  
Description: Descrizione del plugin  
Author: Nome Cognome  
Author URI: http://sito.com  
*/

Questi sono i metadati del plugin che verranno usati da WordPress per identificarlo nel backend. La prima riga dichiara il
nome del plugin, la seconda il numero di versione, la terza la descrizione, la quarta mostra l’autore del plugin e la quinta
l’URL del sito dell’autore del plugin. Quando il plugin viene attivato le informazioni contenute in questi metadati vengono
salvate nel database aggiungendole alla stringa contenuta nel campo active_plugins della tabella wp_options (si
tratta di una stringa serializzata).
Dopo questo blocco iniziale l’autore del plugin può inserire il suo codice che, come abbiamo anticipato, può essere
interamente contenuto nel file principale o basato su file esterni richiamati tramite le funzioni PHP require() o
require_once(). Una volta attivato, il codice del plugin è disponibile globalmente nel flusso di WordPress. Quindi se il
plugin definisce una funzione chiamata my_func() questa sarà disponibile nella nostra installazione di WordPress,
ovviamente nel contesto che le è proprio (frontend o backend) secondo le scelte di design dell’autore del plugin. Quando il
plugin viene disattivato o non è presente, la nostra funzione my_func() non sarà più disponibile.

Percorsi  ed  URL  

C’è una differenza sostanziale tra percorsi ed URL quando si parla di plugin e più in generale di tutto ciò che ha a che fare
con WordPress. Un "percorso" (path) fa riferimento al file system del server che ospita WordPress, mentre un "URL" fa
riferimento al protocollo HTTP e al dominio su cui risiedono i file.

Quindi /home/nomeutente/sito.com/public_html/wp-content/plugins/my_plugin è un percorso,


mentre http://sito.com/wp-content/plugins/my_plugin/ è un URL.

I percorsi vengono usati per includere i file PHP, mentre gli URL per includere i file CSS, JavaScript e le immagini.
WordPress gestisce i percorsi tramite la funzione plugin_dir_path() che restituisce il percorso alla directory del plugin
compreso lo slash finale. Quindi nel file principale del plugin possiamo scrivere:

define( ‘MY_PLUGIN_PATH’, plugin_dir_path( __FILE__  ) );  


// /home/nomeutente/sito.com/public_html/wp-content/plugins/my_plugin/

e quindi includere i file PHP in questo modo:

require_once( MY_PLUGIN_PATH . ‘framework/MyClass.php’ );

Al contrario la funzione plugin_dir_url() restituisce l’URL assoluto alla directory principale del plugin compreso lo slash
finale. Quindi nel file principale del plugin possiamo scrivere:

define( ‘MY_PLUGIN_URL’, plugin_dir_url( __FILE__  ) );  


// http://sito.com/wp-content/plugins/my_plugin/

e quindi usare l’URL in questo modo:

wp_register_script( ‘my’, MY_PLUGIN_URL . ‘js/my.js’, array( ‘jquery’ ), ‘1.0’,


true );

Da segnalare anche la funzione plugins_url() che ha uno scopo identico anche se con parametri diversi.

Tutte queste funzioni si basano sul file o sulla directory passata come parametro per restituire il percorso o l’URL corretto.
In PHP __FILE__ fa riferimento al file corrente in cui viene invocato. Quindi usarlo in my_plugin/my_plugin.php
e in my_plugin/framework/MyClass.php restituirà due valori distinti poiché i file non si trovano nella stessa
directory.

Ora che abbiamo chiara la struttura di un plugin dal punto di vista dell’organizzazione del codice, possiamo entrare nel
merito dello sviluppo del codice di un plugin di WordPress.

Plugin di WordPress e prestazioni


Un plugin performante è un plugin che non ha un impatto sostanziale sulle prestazioni globali di WordPress. In questo
capitolo descriveremo alcuni accorgimenti da adottare per creare plugin performanti.
Il  backend  

WordPress dispone di numerose action che vengono invocate ogni qualvolta si accede ad una sezione del backend. Esistono
action generiche che vengono invocate su più sezioni ed action specifiche che vengono invocate solo su determinate sezioni.

Una buona pratica è quella di limitare al massimo il codice collegato ad action generiche ed usare invece le action più
specifiche attraverso filtri ed hook. La action a cui non si dovrebbero mai associare troppe routine è init. Come suggerisce
il suo nome, questa action è la radice di tutto il flusso del codice di WordPress ed è sempre invocata. WordPress, quindi,
eseguirà sempre il nostro codice, anche dove non ce ne sarebbe bisogno. Su questa action non andrebbe mai legato del
sorgente che comporti operazioni intensive, come query ripetute al database.

Un altro aspetto da tenere presente sin dall’inizio consiste nel verificare cosa accade nel backend una volta attivato il nostro
plugin impostando in wp-config.php la costante WP_DEBUG su true. Anche se questa opzione non serve a monitorare
la performance di un plugin, è tuttavia importante per escludere l’eventualità che i rallentamenti siano causati da codice
errato.

Se un plugin utilizza il database con tabelle personalizzate (come ad esempio un’estensione che gestisce le prenotazioni
online per un sito) tramite la classe wpdb, una buona regola è quella di mettere in cache quelle query per cui non è sempre
necessario avere un refresh immediato.

Il caching delle query può essere implementato con le Transients API di WordPress:

global  $wpdb;  
$results  = get_transient( ‘prenotazioni’ );  
if( $results  ) {  
// loop sui risultati  
} else  {  
$res  = $wpdb->get_results( “SELECT * FROM prenotazioni” );  
set_transient( ‘prenotazioni’, $res, HOUR_IN_SECONDS );  
}

In questo caso abbiamo messo in cache i risultati della query per 1 ora. Quando il tempo è scaduto, il valore della chiave
prenotazioni torna ad essere false ed il processo si ripete con dei nuovi risultati.

In generale queste API possono essere usate per memorizzare qualsiasi tipo di dato, quindi sono molto indicate per
velocizzare alcune operazioni ripetute (come ad esempio la generazione e la visualizzazione di stringhe HTML o CSS).

Un altro aspetto, stavolta più controverso, sono i task programmati usando le API Cron. PHP infatti non ha la capacità di
attivarsi in un determinato momento in modo autonomo: c’è sempre bisogno di una richiesta GET su un file specifico che
eseguirà il codice. Nello specifico, WordPress usa il file wp-cron.php per i suoi cron jobs.

Il problema è che questi cron si attivano quando si visualizza una qualsiasi sezione di un sito Web, sia nel backend che nel
frontend. In pratica la routine di verifica avviene sempre, e questo ha un impatto sulla performance.

Quindi se si vogliono utilizzare i cron nei plugin si dovrebbe sempre tenere presente questa particolarità per evitare di
sovraccaricare inutilmente WordPress.

Il  frontend  

Nel frontend bisogna applicare un modello specifico di ottimizzazione che parte sempre dalle condizioni peggiori per poi
scalare verso condizioni migliori. Le condizioni peggiori sono quelle rappresentate da un sito poco performante e lento a
rispondere. Se sviluppiamo in locale abbiamo bisogno di un applicativo come Sloppy per emulare le condizioni peggiori,
come per esempio connessioni molto lente che aiutano a capire dove intervenire per migliorare la situazione.
Il codice CSS e JavaScript va fornito in due formati: uno compresso e minimizzato da usare effettivamente sul sito Internet
ed un formato non compresso per le eventuali modifiche da parte dell’utente (se si segue la licenza GPL).

Le immagini da usare con i CSS devono essere ottimizzate. Se usate le icone, è preferibile impiegare le sprite CSS per
ridurre al minimo le richieste GET.

Se si utilizzano invece dei Web font per generare le icone, il peso complessivo dei file dovrà essere limitato. Si tenga
presente che un Web font viene rilasciato in diversi formati (TTF, SVG, EOT ecc.).

In questo caso la regola da seguire è semplice: inserire il codice CSS e JavaScript solo dove è richiesto e non in tutto il sito
Internet. Se sappiamo ad esempio che il nostro codice verrà usato solo nei custom post type di tipo prenotazioni
possiamo scrivere:

if( is_singular( ‘prenotazioni’ ) ) {  


wp_register_script( ‘booking’, plugins_url() . ‘/my-plugin/js/booking.min.js’,
false, ‘1.0’, true );  
wp_enqueue_script( ‘booking’ );  
}

Gli script JavaScript andrebbero sempre inseriti prima della chiusura dell’elemento <body> per velocizzare il caricamento
delle pagine. Ecco perché usiamo l’ultimo parametro della funzione wp_register_script() impostato su true.
Inoltre, se non possiamo limitare l’uso del codice a sezioni specifiche, è sempre buona norma creare un namespace per il
codice CSS e JavaScript usando i prefissi per evitare conflitti, ad esempio:

#my-plugin-booking-form {  
}

In JavaScript:

(function( $ ) {  
$.MyPluginBooking = {};  
//…  
})( jQuery );

Le ambiguità generano rallentamenti, perché i browser devono comunque risolverle, mentre la specificità implica velocità.

Conclusione  

Con dei semplici accorgimenti possiamo creare plugin snelli che non hanno un grande impatto sulle prestazioni complessive
di WordPress; Nel prossimo capitolo verrà affrontato il discorso relativo a plugin e sicurezza.

Plugin di WordPress e sicurezza


In questo capitolo affronteremo il tema della sicurezza dei plugin di WordPress. Si possono riassumere le pratiche
consigliate per questo argomento in una sola espressione: “essere paranoici” o, se non altro, estremamente prudenti.

Analisi  di  una  procedura  per  l’attacco  contro  un  sito  basato  su  WordPress  

Anche se esistono plugin che affermano di nascondere un’installazione di WordPress, esistono tuttavia tool automatici per
la scansione dei siti che possono letteralmente eseguire una radiografia di un sito. Non solo un malintenzionato sa che
usiamo WordPress, ma sa anche che plugin stiamo utilizzando, quali sono i temi installati e molto altro ancora. Questo è il
prezzo da pagare per aver pubblicato un sito pubblico.
Una volta effettuata la scansione, un malintenzionato di solito passa alla ricerca di vulnerabilità nei temi e nei plugin e, se
WordPress non è aggiornato, anche nel Core di WordPress stesso. Trovata la vulnerabilità, l’attaccante può usare un exploit
già disponibile in rete o scriverne uno (questo nel caso in cui il malintenzionato sia molto esperto).

All’exploit, eseguito da remoto su un file specifico dell’installazione di WordPress, segue il payload, ossia il codice
malevolo che verrà eseguito. A questo punto se PHP viene eseguito con i vincoli dell’utenza corrente, i danni causati
interesseranno lo spazio Web dell’utente stesso. Se questi vincoli non dovessero esistere, il codice malevolo potrà
propagarsi su più utenze e quindi su più siti Internet.

A questo punto il danno sarà ormai fatto. L’unica soluzione valida rimane come al solito è la prevenzione.

Difendersi  dagli  input  imprevisti  

PHP gestisce i metodi HTTP GET e POST e i file con array superglobali. Quando dobbiamo manipolare un input esterno,
dobbiamo sempre validare e filtrare i dati in ingresso. In altre parole dobbiamo considerare qualsiasi forma di input come
potenzialmente pericoloso ed agire di conseguenza.

Quindi sarà necessario:

• filtrare  le  query  SQL  con  il  metodo  prepare()  della  classe  wpdb;  
• filtrare  ogni  variabile  veicolata  tramite  GET  o  POST  da  inserire  nel  flusso  di  output  con  le  
funzioni  di  escape  (con  prefisso  esc_)  di  WordPress;  
• validare  i  dati  inseriti  dagli  utenti  secondo  il  formato  dati  richiesto  (numero,  stringa,  
indirizzo  e-­‐mail..  );  
• se  si  gestiscono  file  (upload,  manipolazione,  inclusione..)  verificare  sempre  che  il  file  sia  
del  tipo  corretto  e  che  l’operazione  che  l’utente  vuole  eseguire  sia  consentita;  
• se  si  usano  le  sessioni  di  PHP,  validare  sempre  la  sessione  corrente  tramite  token  o  
autenticazione  utente.  

Si analizzi il codice seguente:

global  $wpdb;  
$reservation_id  = $_GET[‘res_id’];  
$reservation  = $wpdb->get_results( “SELECT * FROM reservations WHERE id =
$reservation_id” );

Tendenzialmente la variabile GET potrebbe contenere qualsiasi valore ed è una porta spalancata per un tentativo di SQL
injection. Sappiamo che ci dobbiamo aspettare un valore numerico intero. Quindi come validazione preliminare e
grossolana potremmo scrivere:

$sane_res_id  = 0;  
if( is_numeric( $reservation_id  ) ) {  
$r_id  = intval( $reservation_id  );  
if( filter_var( $r_id, FILTER_VALIDATE_INT ) ) {  
$sane_res_id  = $r_id;  
}  
}

Tale accorgimento è sufficiente ai fini della sicurezza? Assolutamente no. Quindi usiamo wpdb::prepare():

$prepared  = $wpdb->prepare( “SELECT * FROM reservations  


WHERE id = %d”, array( $sane_res_id  ) );  
$reservation  = $wpdb->get_results( $prepared  );
Sulla base di quanto già detto, consideriamo ora quest’altro esempio:

$title  = $_GET[‘title’];  
echo  ‘<h1>’ . $title  . ‘</h1>’;

Questo è un esempio tipico in cui può verificarsi un attacco di tipo XSS (Cross-site scripting), ossia l’inserimento nella
pagina di codice JavaScript malevolo. Per prevenirlo dobbiamo fare in modo che la stringa passata non contenga appunto
tale codice:

$raw_title  = wp_kses( $title  );  


echo  esc_html( $raw_title  );

Qui abbiamo semplicemente combinato le funzioni di WordPress wp_kses() ed esc_html() per essere sicuri che la stringa
non contenga nessun tag HTML.

Abbiamo visto come i malintenzionati cerchino di eseguire il codice dei file da remoto. Per impedire questa pratica
possiamo utilizzare una costante PHP globale nei nostri plugin:

define( ‘MY_PLUGIN_C’, ‘1’ );

Quindi nei nostri file eseguiamo questa verifica sempre all’inizio:

if( !defined( ‘MY_PLUGIN_C’ ) ) {  


exit();  
}

In questo modo il nostro codice potrà essere eseguito solo all’interno del contesto del plugin.

Osserviamo quindi il codice mostrato di seguito:

if( isset( $_GET['pdf'] ) ) {  


$pdf_base_url  = 'http://sito.com/wp-content/uploads/pdf/';  
$pdf_base_path  = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/uploads/pdf/';  
$pdf  = $_GET['pdf'];  
$pdf_full_url  = $pdf_base_url  . $pdf;  
$pdf_full_path  = $pdf_base_path  . $pdf;  
if( preg_match( '/\.pdf$/', $pdf  ) ) {  
if( file_exists( $pdf_full_path  ) ) {  
$finfo  = finfo_open( FILEINFO_MIME_TYPE );  
$mimetype  = finfo_file( $finfo, $pdf_full_path  );  
finfo_close( $finfo  );  
if( $mimetype  == 'application/pdf'  ) {  
header( 'Content-type: application/pdf'  );  
header( 'Content-Disposition: attachment; filename="'  . $pdf  . '"'  );  
readfile( $pdf_full_url  );  
}  
}  
}  
}

Una variabile GET contiene il nome di un file PDF da scaricare. I PDF nel nostro esempio sono stati uploadati tramite FTP
perché troppo pesanti per la Media Library. Nell’esempio abbiamo verificato che il nome del file sia valido in prima istanza.
Quindi abbiamo controllato che il file richiesto sia effettivamente un file PDF verificando il suo MIME Type. Se non
avessimo eseguito questa operazione, si sarebbe potuto scaricare qualsiasi tipo di file.
La verifica del MIME Type si rivela fondamentale anche nella gestione degli upload. In questo caso è inutile implementare
un sistema di upload personalizzato, sarebbe meglio invece cercare di utilizzare sempre la Media Library e le sue API per la
gestione degli allegati e dei file.

Ora, si ipotizzi il caso di un carrello per un e-commerce. Quando l’utente sceglie un prodotto, questo viene aggiunto
all’array superglobale $_SESSION. Ma come facciamo a sapere che sia sempre lo stesso utente ad effettuare tali
operazioni?

In questo caso dobbiamo impostare un token di sessione:

if( !isset( $_SESSION['my-token'] ) ) {  


$token  = md5( $_SERVER['HTTP_USER_AGENT'] );  
$_SESSION['my-token'] = $token;  
}

Quindi ad ogni cambio pagina va verificato il token creato:

if( isset( $_SESSION['my-token'] ) ) {  


$token  = md5( $_SERVER['HTTP_USER_AGENT'] );  
if( $_SESSION['my-token'] == $token  ) {  
//...  
}  
}

Alla fine della procedura d’acquisto la sessione dovrà essere distrutta e con essa il token di sessione.

Conclusione  

Questa introduzione alla sicurezza dei plugin di WordPress è da ricollegarsi direttamente al tema più generale della
sicurezza in PHP. Essere a conoscenza dei rischi è il primo passo per evitarli.

Funzionalità ed usabilità dei plugin di


WordPress
In questo capitolo affronteremo uno degli argomenti più importanti che riguardano i plugin di WordPress, ossia la loro
usabilità ed il tipo di funzionalità fornite. Gli argomenti trattati vertono infatti sull’interazione con gli utenti, perché in linea
di massima nessuno vuole creare un plugin difficile da usare o incompleto nelle sue funzionalità.

Press  any  key:  l’utente  ideale  e  l’utente  reale  

Un aneddoto molto in voga che si racconta a proposito degli utenti finali è quello del “Press any key” e dell’avvertenza che
recita “Non esiste il tasto Any”. L’aneddoto vuole ricordare che non è possibile conoscere in anticipo il livello tecnico degli
utenti, quindi occorre adottare una strategia di tipo “difensivo”.

Quando si crea un plugin di WordPress è necessario tenere in considerazione che:

• i  nostri  utenti  potrebbero  avere  una  laurea  in  informatica  o  essere  degli  “analfabeti”  
informatici;  
• quello  che  per  noi  è  scontato  ed  intuitivo,  per  un  utente  potrebbe  essere  contorto  e  
complesso;  
• gli  utenti  vogliono  usare  il  plugin  da  subito.  

Stiamo quindi parlando degli utenti reali e non di quelli “ideali”. Sulla base di tali osservazioni, quello che possiamo fare in
concreto è:

• creare  un’interfaccia  semplice  ed  intuitiva  basandosi  sull’approccio  “Less  is  more“;  
• usare  delle  etichette  chiare  ed  autoesplicative;  
• spiegare  brevemente  in  ogni  sezione  delle  opzioni  a  cosa  serve  quella  pagina;  
• fornire  una  o  più  pagine  di  documentazione;  
• fornire  una  o  più  pagine  con  le  risposte  alle  domande  frequenti  (FAQ);  
• fornire  un  form  di  contatti  per  inoltrare  una  richiesta  di  supporto.  

Less  is  more:  siamo  sempre  in  WordPress?  

Molti plugin forniscono un pannello di controllo che non ha nulla a che fare con il backend di WordPress a livello di
interfaccia visuale. Questa scelta di design rende le cose più complicate per gli utenti perché essi vengono costretti ad
abituarsi di colpo a qualcosa di radicalmente diverso rispetto all’impostazione precedente. Per limitare l’insorgere di tali
problematiche è quindi consigliabile usare:

• i  font  già  presenti  in  WordPress;  


• i  colori  e  gli  sfondi  di  WordPress;  
• le  convenzioni  grafiche  di  WordPress  per  gli  elementi  interattivi  come  per  esempio  form,  
pulsanti  etc.;  
• le  icone  già  presenti  in  WordPress  o  icone  similari;  
• un  layout  lineare  (non  vinceremo  alcun  design  award  perché  non  è  quello  il  nostro  scopo).  

Etichette:  facciamoci  capire  

Quando “etichettiamo” una sezione o un elemento interattivo non dobbiamo lasciare spazio a dubbi: se una sezione contiene
i dettagli dell’account Twitter di un utente, la chiameremo “Impostazioni Twitter” e sui campi della sezione useremo
etichette come “Nome utente” e “Password”.

In altre parole dobbiamo sempre puntare alla massima chiarezza e descrittività possibile, quando generiamo dubbi creiamo
problemi per gli utilizzatori.

Spiegare,  sempre!  

“Cosa devo fare ora?” o “A cosa serve questo?” o anche “Dove mi trovo?” sono domande che si pongono spesso gli utenti.
Noi non dobbiamo lasciare che questi ultimi si pongano tali domande, dobbiamo invece anticiparle e fornire già le risposte.
Come? Usando brevi descrizioni nelle sezioni e nei componenti delle opzioni.

Quindi, per proporre un esempio in merito::

• Etichetta:  Nome  utente  


• Spiegazione:  Inserisci  il  tuo  nome  utente  di  Twitter  (senza  il  carattere  ‘@’  )  

Non lasciate soli gli utenti con le loro domande.


Documentazione,  FAQ  e  supporto  

La documentazione di un plugin dovrebbe essere sempre divisa in due sezioni ben distinte: una per gli utenti ed una per gli
sviluppatori. Mai e poi mai dovremmo mischiare insieme le due cose. Ciò che è utile per un developer è spesso inutile (o
semplicemente troppo complicato) per un utente e ciò che è utile per un utente spesso è scontato per un developer.

Le FAQ sono un work in progress: queste vanno aggiornate man mano che riceviamo il feedback dagli utenti. Non
dovrebbero mai rimanere le stesse, ma andrebbero aggiornate man mano che gli utenti ci segnalano dubbi o problemi.

Il supporto è invece molto più complesso da gestire: la frase ricorrente “non funziona” può voler dire tutto e niente ed in
effetti non è di alcuna utilità per uno sviluppatore. Quindi nel form di supporto o sul forum di WordPress dovremmo
chiedere o raccogliere dati tecnici precisi come:

• versione  di  WordPress;  


• versione  di  PHP;  
• plugin  installati;  
• tema  in  uso.  

Solo avendo a disposizione questi dati possiamo realmente intervenire per aiutare gli utenti che ce ne fanno richiesta.

Funzionalità  

Due sono gli errori comuni quando si parla di funzionalità di un plugin:

1. mancanza  di  funzionalità;  


2. eccesso  di  funzionalità.  

Se creo un plugin per Twitter che pubblichi su Twitter i nuovi post dovrò avere almeno queste funzionalità che forniscano la
capacità di:

• abbreviare  gli  URL;  


• pubblicare  anche  i  post  programmati;  
• pubblicare  anche  le  modifiche  ai  post;  
• inviare  un  tweet  personalizzato;  
• riconoscere  username  e  hashtag  di  Twitter.  

Visualizzare la timeline dell’utente, effettuare ricerche o altro sono caratteristiche utili ma non indispensabili al nostro
plugin: dobbiamo sempre attenerci allo scopo per cui esso è stato creato. Se gli utenti ce ne faranno richiesta, possiamo
certamente aggiungere nuove caratteristiche ma senza mai esagerare.

Codice OOP nei plugin di WordPress


In questo articolo introdurremo alcuni dei concetti chiave per programmare in modo Object-Oriented in WordPress;
requisiti necessari sono la conoscenza dell’OOP in PHP e competenze di base sul funzionamento del CMS.

Un  CMS  misto:  OOP  e  programmazione  procedurale  in  WordPress  

Un mito comune riguardante WordPress è quello secondo cui il codice sorgente di questo CMS sia interamente procedurale
nel suo design. Nulla di più falso: la scelta di design di WordPress è stata quella di costruire le fondamenta del CMS
usando le classi e di esporre i metodi e le proprietà di tali classi tramite funzioni e variabili globali. Ad esempio tutti noi
sappiamo che il Loop principale di WordPress – ossia il ciclo attraverso cui vengono reperiti i contenuti – può di solito
presentarsi come segue:

if( have_posts() ) {  
while( have_posts() ) {  
the_post();  
}  
}

Apparentemente tale codice è interamente procedurale, in realtà tutte le funzioni che abbiamo utilizzato non sono altro che
una scorciatoia per il seguente codice OOP:

$loop  = new  WP_Query( array( 'posts_per_page'  => -1 ) );  


if( $loop->have_posts() ) {  
while( $loop->have_posts() ) {  
$loop->the_post();  
}  
}

Lo stesso concetto vale per le funzioni get_posts() e query_posts(), esse sono tutte basate sulla classe WP_Query; più
precisamente, tutto ciò che in WordPress ha a che fare con il Loop – ossia con il reperimento dei contenuti dal database
(post, pagine, allegati) – dipende direttamente da tale classe e non può in alcun modo prescindervi.

Ma non basta: anche la temporizzazione degli eventi, la gestione degli errori, delle richieste AJAX, delle query dirette al
database, degli utenti e dei loro ruoli, dei menu di navigazione, i widget e altro ancora, sono tutte funzionalità affidate alle
classi.

In definitiva, noi usiamo quasi sempre funzioni in WordPress, ma in realtà stiamo adottando le sue classi che restano
nascoste dietro le quinte.

Perchè  usare  l’OOP?  

Abbiamo detto che in WordPress le funzioni svolgono egregiamente il loro compito, quindi, per aggiungere una funzionalità
al tema utilizzato è solitamente sufficiente modificare il file “functions.php” (il nome è significativo) con il nostro codice e
ottenere così l’effetto desiderato. Se per esempio volessimo creare uno shortcode per visualizzare una citazione di blocco,
dovremmo semplicemente aggiungere il seguente codice:

function  my_pullquote( $content  ) {  


return  '<blockquote class="pullquote">'  . $content  . '</blockquote>';  
}  
add_shortcode( 'my-pullquote', 'my_pullquote'  );

Ma cosa succederebbe se avessimo più di uno shortcode da aggiungere? A livello di gestione e manutenibilità del codice ci
ritroveremmo con un file “functions.php” letteralmente traboccante di funzioni, per cui ogni volta che dovessimo modificare
una funzionalità saremmo costretti a ricordarci in quale funzione l’abbiamo definita. Si tratta di uno scenario davvero
difficile da gestire. Le classi ci permettono invece di raggruppare il codice in moduli separati, ciascuno con una propria
logica ed una propria struttura; quindi, per gli shortcode potremmo definire una classe apposita:

class  MyThemeShortcodes {  
}

Al suo interno saranno i metodi della classe a definire le azioni legate a ciascuno shortcode:

class  MyThemeShortcodes {  
public  function  __construct() {  
add_shortcode( 'my-pullquote', array( &$this, 'createPullQuote'  ) );  
}  
public  function  createPullQuote( $content  ) {  
return  '<blockquote class="pullquote">'  . $content  .
'</blockquote>';  
}  
}  
$myThemeShortcodes  = new  MyThemeShortcodes();

Nel caso specifico l’istanza della classe richiama direttamente la funzione di WordPress add_shortcode() che crea lo
shortcode. Quindi in “functions.php” richiameremo i moduli desiderati:

require_once( TEMPLATEPATH . '/framework/MyThemeShortcodes.php'  );

Si potrebbe obiettare che questo tipo di classi in WordPress non sono altro che dei wrapper per metodi pubblici, ma in realtà
non è così; si supponga ad esempio di voler eliminare la marcatura aggiuntiva inserita da WordPress nel contenuto degli
shortcode:

private  function  _removeWPAutop( $content  ) {  


$content  = do_shortcode( shortcode_unautop( $content  ) );  
$content  = preg_replace( '#^<\/p>|^<br \/>|<p>$#', '', $content  );  
return  $content;  
}
public  function  createPullQuote( $content  ) {  
return  '<blockquote class="pullquote">'  .  
$this->_removeWPAutop( $content  ) . '</blockquote>';  
}

Come si può notare, viene applicata la stessa distinzione alla base della logica OOP di PHP: un metodo privato opera
all’interno della sua classe di appartenenza secondo il principio dell’incapsulamento.

Il metodo è privato perché al di fuori della classe che gestisce gli shortcode non sarebbe di alcuna utilità. Infatti il problema
della marcatura extra è peculiare degli shortcode di WordPress. Lo stesso principio si applica alle proprietà di queste classi,
ad esempio potremmo volere che sia l’utente a scegliere di rimuovere la marcatura dagli shortcode o mantenerla:

class  MyThemeShortcodes {  
public  $removeAutop  = false;  
public  function  __construct() {  
if(get_option('my-no-autop')) {  
$this->removeAutop = (bool) get_option('my-no-autop');  
}
//...  
}  
public  function  createPullQuote( $content  ) {  
if($this->removeAutop) {  
// rimuove la marcatura  
} else  {  
// non la rimuove  
}  
}  
}

In questo caso usiamo una proprietà pubblica in modo da poter comunicare lo status della classe alle altre classi che
andremo a definire, ossia la scelta di non intervenire sul contenuto degli shortcode.
Buone pratiche nella scrittura del codice in
WordPress
Nel precedente articolo abbiamo introdotto alcuni concetti fondamentali della programmazione OO in WordPress. In
questo articolo tratteremo invece delle convenzioni stilistiche per la scrittura del codice OO nel noto Blog engine.

Struttura  dei  file  e  delle  directory  

Sebbene WordPress consenta di fatto la scrittura del nostro intero codice nel file functions.php di un tema o nel file
principale di un plugin, l’OOP prevede invece la creazione di una gerarchia di directory contenente i file delle nostre classi;
tale gerarchia va sempre creata al di sotto della directory principale del tema o del plugin. Una buona pratica è quella di
raggruppare insieme le classi che svolgono compiti analoghi. Ecco un esempio di questa gerarchia:

• /framework/    
o /shortcodes/  
o /post-­‐types/  
o /widgets/  
o /theme-­‐settings/  

I nomi delle directory dovranno essere autoesplicativi nel senso che assegnare nomi abbreviati o quantomeno criptici alle
directory renderà la manutenzione futura molto più difficile, inoltre, se avete intenzione di rivendere il vostro lavoro sul
mercato, tenete presente che una struttura chiara delle directory vi eviterà spesso di dover rispondere alle classiche richieste
di supporto del tipo “dove trovo il codice X?”.
Per quanto riguarda invece i nomi delle classi, la pratica corrente è quella di creare un file PHP per ciascuna classe.
Solitamente la struttura del nome di questi file è così composta:

PrefissoTemaOPluginNomeClasse.php

Come si può notare viene utilizzata la notazione camel-case. Il prefisso del tema o del plugin viene preposto al nome della
classe allo scopo di creare sia un riferimento visivo alle classi sia un contesto di applicazione per esse. Se volete invece
creare un framework da riutilizzare su più temi o plugin, allora il prefisso sarà quello del vostro framework.
Se utilizzate lo standard Zend, allora il nome della classe avrà come primo componente il nome della directory seguito dal
nome della classe. Ciascuna parte del nome sarà separata da un underscore:

Prefisso_Directory_Nome_Classe.php

Una pratica comune in WordPress è quella di evitare che le classi interagiscano direttamente con i temi nel frontend, per
questo motivo vengono create delle funzioni ad hoc che potranno essere usate nel frontend semplicemente richiamando i
metodi delle classi.
Queste funzioni dovranno essere raggruppate in file specifici, come ad esempio frontend-funcs.php e quindi
richiamate nel loop principale di WordPress.

Scrittura  del  codice  

WordPress dispone di uno standard ben definito per la scrittura del codice PHP, questo standard, tuttavia, si applica per
quegli sviluppatori che intendono contribuire al Core del CMS. Ad un’attenta lettura, come del resto accade anche per molti
altri CMS, solo alcune di queste pratiche raccomandate trova un riscontro universale nell’ambito generale di PHP. Per
esempio l’uso delle virgolette è una pratica condivisa, mentre l’uso dei tab al posto degli spazi non lo è.
Sicuramente una pratica molto utile è la spaziatura intorno alle parentesi tonde dei blocchi. Quindi:
foreach($foo  as  $bar) {  
...  
}

è sconsigliato, mentre:

foreach( $foo  as  $bar  ) {  


...  
}

è consigliato, questo perché la spaziatura facilita la lettura e la comprensione del codice.


WordPress insiste molto sul fatto che le parti del nome di una funzione debbano essere separate da un underscore:

function  my_function( $param1  = 'foo', $param2  = 'bar'  ) { ...}

Lo stesso principio, secondo gli sviluppatori di WordPress, dovrebbe applicarsi anche ai nomi delle classi:

class  Walker_Category extends  Walker { [...] }

Tuttavia questa pratica non è universalmente accettata, quindi le seguenti alternative sono valide:

class  PrefixMyClass {  
//...  
}
class  Prefix_Dir_My_Class  
{  
// Zend  
}

Per quanto riguarda i nomi dei metodi e delle proprietà si segue in genere la notazione camel-case, usando un underscore
come prefisso per i metodi e le proprietà con visibilità protected o private:

class  PrefixMyClass {  
protected  $_testProperty;  
private  function  _sampleMethod() { }  
}

Una pratica assolutamente sconsigliata è quella che riguarda l’uso dell’operatore di scope su metodi non statici. Anche se in
PHP funziona ugualmente, tuttavia una pratica come:

class  PrefixMyClass {  
public  function  method() { }  
}
PrefixMyClass::method();

è errata perché dovrebbe essere utilizzata solo se il metodo di cui sopra fosse stato dichiarato come static.
I nomi delle costanti, sia quelle definite in modo globale sia quelle definite in una classe, andrebbero sempre in lettere
maiuscole, separate da un underscore:

class  PrefixMyClass {  
const  MY_VALUE = 'OK';  
}
Se i vostri file contengono soltanto codice PHP, allora potrete omettere il delimitatore PHP di chiusura, stando bene attenti
che il vostro file non contenga spazi alla fine. Questa pratica ci permette di evitare il tristemente noto errore Headers
already sent quando includiamo il nostro codice nel flusso di WordPress.

Conclusioni  

In questo articolo abbiamo definito alcune semplici linee guida da seguire nella scrittura e nella gestione del nostro codice
OO in WordPress, tali linee guida si riveleranno fondamentali quando dovremo affrontare progetti complessi. Nella
prossima lezione presenteremo un’introduzione alla programmazione per oggetti nei plugin di WordPress

Integrare i plugin con i temi di WordPress


I plugin di WordPress non sono concepiti per essere delle “isole”, cioè entità a sé stanti. In WordPress un plugin deve poter
interagire con i temi in uso nell’installazione. In questo capitolo vedremo appunto alcuni modi per far si che i nostri plugin
si integrino con il tema corrente.

Creare  delle  API  per  i  temi  

Il celebre plugin multilingua WPML a prima vista potrebbe sembrare come un’implementazione monolitica che lascia ben
poco spazio all’interazione con il codice esterno dei temi.

In realtà questo plugin, come altri, dispone di API specifiche che permettono agli autori di temi di poter interagire con esso,
ad esempio creando un selettore di lingua personalizzato o ottenendo la traduzione di alcune stringhe.

Se osserviamo la pagina dedicata alle API di WPML noteremo che tali interfacce sono state implementate usando due
tecniche già utilizzate da WordPress, ossia:

1. action  personalizzate;  
2. funzioni  globali;  
3. costanti.  

WPML adotta lo stesso approccio di WordPress nella gestione del codice: l’OOP viene usato per gestire tramite classi il
funzionamento core del plugin ma non deve essere direttamente invocato nei temi. Al contrario i temi dovranno utilizzare le
API pubbliche, ossia le action e le funzioni globali.

Vediamo ora come implementare le nostre API partendo dalle basi, ossia dalle funzioni.

Le  funzioni  

Le funzioni possono avere o non avere argomenti. Usare funzioni senza argomenti può avere senso se stiamo inserendo del
contenuto che non necessita di essere modificato, ma se vogliamo permettere agli autori di temi di gestire il nostro codice
con maggiore facilità, allora creare funzioni con argomenti è la scelta consigliata.

Ipotizziamo di avere implementato un plugin che gestisce degli slideshow tramite custom post type e tassonomie. Nella
nostra classe core avremo:

class  My_Slideshow {  
//...  
public  function  render( $slideshow  ) {  
$args  = array(  
'post_type'  => 'slides',  
'slideshow'  => $slideshow,  
'posts_per_page'  => -1  
);  
$loop  = new  WP_Query( $args  );  
if( $loop->have_posts() ) {  
// Crea lo slideshow  
}  
}  
}  
$mySlideshow  = new  My_Slideshow();

Possiamo creare una funzione specifica globale che, dato lo slug di una tassonomia, visualizzi uno slideshow specifico nel
tema:

function  my_slideshow_show( $slideshow  ) {  


global  $mySlideshow;  
echo  $mySlideshow->render( $slideshow  );  
}

Quindi un autore potrà usare la nostra funzione nel modo seguente all’interno del suo tema:

if( is_home() || is_front_page() ):  


my_slideshow_show( 'main'  );  
endif;

Quella che abbiamo appena creato è una funzione che agisce direttamente sul tema modificandolo. Possiamo anche creare
funzioni che restituiscano un valore impostato nel plugin, ad esempio attraverso le sue opzioni o i suoi custom field
(funzioni getter):

function  my_slideshow_get_animation_type() {  
$type  = get_option( 'my_slideshow_animation_type'  );  
return  $type;  
}

In questo caso l’autore del tema potrà usare il valore restituito per gestire alcune scelte a livello di codice CSS o JavaScript:

$anim_type  = my_slideshow_get_animation_type();  
if( $anim_type  == 'fade'  ):  
// Codice  
else:  
// Codice  
endif;

Le  costanti  

Il nostro plugin può anche operare tenendo presente le preferenze espresse dall’autore del tema sotto forma di costanti PHP
definite nel file functions.php del tema. Dato che le costanti PHP sono immutabili e non possono essere ridefinite,
pena un “errore fatale”, dobbiamo prima verificare che l’autore del tema le abbia dichiarate:

if( defined( 'MY_SLIDESHOW_NO_PLUGIN_CSS'  ) ) {  


if( MY_SLIDESHOW_NO_PLUGIN_CSS ) {  
// Non carichiamo i nostri stili CSS  
} else  {  
// Carichiamo i nostri stili CSS  
}  
} else  {  
// Default  
}

In questo caso se la costante MY_SLIDESHOW_NO_PLUGIN_CSS è stata impostata su true non andremo a caricare i
nostri stili CSS ma lasceremo all’autore il compito di definire il layout dello slideshow.

Le  action  

Alla base delle action personalizzate ci sono due funzioni di WordPress:

1. add_action();  
2. do_action().  

Leggendo la documentazione appare chiaro il motivo per cui abbiamo affrontato le funzioni come primo argomento di
questo capitolo: le action personalizzate non sono altro che funzioni che vengono registrate in WordPress tramite
add_action() e che poi possono essere eseguite nei temi con la funzione do_action().

Ritornando all’esempio della nostra funzione che visualizza uno slideshow, possiamo quindi ridefinirla come action:

add_action( 'slideshow_show', 'my_slideshow_show', 10, 2 );

La funzione accetta come sappiamo un argomento che però verrà delegato alla funzione do_action():

if( is_home() || is_front_page() ):  


do_action( 'slideshow_show', 'main'  );  
endif;

In questo modo l’autore del tema ha a disposizione uno strumento ancora più flessibile per interagire con il nostro plugin.

Gestione codice lato client nei plugin di


WordPress
In questo capitolo spiegheremo come andrebbe strutturato il codice lato client (CSS e JavaScript) nei nostri plugin di
WordPress. Si tratta di un aspetto fondamentale per poter creare dei plugin performanti ed efficienti non solo sul server Web
ma anche lato browser.

Inclusione  del  codice  JavaScript  e  CSS  

WordPress opera una distinzione tra il codice lato client inserito nel backend e quello inserito nel frontend, ossia nella
sezione amministrativa e nel sito. Sono quindi presenti due action distinte:

1. admin_enqueue_scripts  
2. wp_enqueue_scripts  

La prima action è per il backend, la seconda per il frontend. Anche se i loro nomi potrebbero trarre in inganno, queste due
action servono per includere i file JavaScript e CSS, come nell’esempio seguente:

function  add_js() {  
wp_register_script( ‘my’, plugins_url() . ‘/plugin/js/my.js’ );  
wp_enqueue_script( ‘my’ );  
}  
add_action( ‘wp_enqueue_scripts’, ‘add_js’ );

In questo caso le funzioni di WordPress da utilizzare sono quelle elencate di seguito:

1. wp_register_script()  
2. wp_enqueue_script()  
3. wp_register_style()  
4. wp_enqueue_style()  
5. wp_script_is()  
6. wp_style_is()  

Per gli autori di plugin, anche se può sembrare strano, le funzioni più importanti per scrivere plugin flessibili sono le ultime
due: servono infatti a verificare che uno script o un file CSS non sia già stato incluso. A questo proposito immaginiamo il
caso in cui un tema usi il framework JavaScript jQuery, scenario molto comune. Il seguente codice ci eviterà di
compromettere il frontend:

if( !wp_script_is( ‘jquery’ ) ) {  


wp_enqueue_script( ‘jquery’ );  
}

WordPress dispone di molti script preinstallati, tra cui il già citato jQuery; in questo caso, dato che il nostro plugin usa
jQuery, prima di includerlo dobbiamo verificare che non sia già presente.

Se non avessimo effettuato questa verifica avremmo avuto due copie di jQuery sullo stesso sito, il che avrebbe generato
errori fatali a cascata. Lo stesso principio si applica per i file CSS.

Struttura  del  codice  JavaScript  

WordPress, specialmente con jQuery, spinge gli autori ad usare un namespace per il proprio codice JavaScript; a tal
proposito avrete sicuramente osservato questo modo di usare jQuery in WordPress:

(function( $ ) {  
// codice  
})( jQuery );

Si tratta di una funzione self-executing che assegna alla variabile $ l’oggetto

jQuery
.  In  questo  modo  possiamo  usare  jQuery  direttamente  con  il  suo  alias.  

In JavaScript quando usiamo questo pattern creiamo una sandbox in cui il nostro sorgente può sì operare sulle pagine ma
resta isolato dal resto del codice JavaScript presente nel sito Web.

Questo fattore è fondamentale, dato che noi non possiamo sapere se i nomi delle nostre variabili, delle funzioni e degli
oggetti siano stati già usati da qualche altro script, in un plugin o dal tema.

A differenza di PHP, JavaScript non interrompe l’esecuzione del codice se una variabile viene ad esempio ridefinita. Molto
semplicemente, la variabile creata dopo la prima ne sovrascrive il valore. La stessa cosa, purtroppo, vale anche per le
funzioni e per gli oggetti.
Oltre che con la sandbox che abbiamo già analizzato, possiamo rafforzare ulteriormente il nostro codice usando un prefisso
da usare con funzioni e oggetti. Un altro accorgimento fondamentale è quello di evitare ad ogni costo le variabili globali ed
affidarci invece al contesto (scope) creato dal nostro codice.

Struttura  del  codice  CSS  

Il principio della creazione di un namespace per il nostro codice si applica anche ai CSS con una fondamentale differenza:
nei CSS i prefissi sono l’unico sistema. Possiamo aggiungere un prefisso ai selettori di classe e di ID in questo modo:

#mioplugin-container { … }  
.mioplugin-item { … }

mioplugin è il nostro prefisso che non solo ci mette al riparo da possibili conflitti, ma permette anche agli autori ed agli
utenti di modificare i nostri stili con maggiore facilità.

Una volta creato un namespace possiamo sfruttare il contesto creato dai selettori per definire regole più specifiche:

#mioplugin-container .mioplugin-item a { … }

Sfruttando la cascata possiamo indirizzare le nostre regole con maggiore precisione. Se vi state chiedendo come altri utenti
possano sfruttare il nostro namespace creato dai prefissi, ecco un esempio:

[class^=“mioplugin”] * {  
font-family: Arial, sans-serif  !important;  
}

In questo caso gli utenti possono effettuare un reset globale sui nostri elementi senza dover conoscere necessariamente il
nome dell’elemento. Un notevole vantaggio.

API, filtri e hook per la creazione dei plugin di


WordPress
In questa sezione forniremo un’introduzione alle API, ai filtri ed agli hook di WordPress. Più che offrire una trattazione
esaustiva, ci concentreremo sui modi in cui possiamo apprendere ed usare velocemente queste caratteristiche
dell’applicazione.

API  

Le API (Application Programming Interface) di WordPress si suddividono in diverse sezioni. Ogni sezione comprende in
genere due tipi di argomenti associati:

1. classi  
2. funzioni  

Le classi sono una scelta obbligatoria solo in alcuni casi, perché il principio chiave di WordPress è quello di permettere agli
autori di temi e plugin di utilizzare le funzioni. Tutte le funzioni di WordPress fanno riferimento ad una classe del Core. Di
fatto le funzioni nascondono la logica della classe secondo il principio della modularità. Quando si usa una funzione
bisogna leggere nella documentazione tre parti fondamentali:

1. parametri  
2. valori  di  ritorno  
3. casi  d’uso  

WordPress in genere usa gli array associativi per assegnare alle funzioni dei parametri predefiniti. A differenza del
tradizionale modo con cui i parametri predefiniti vengono passati alle funzioni in PHP, in questo caso l’ordine dei parametri
non è rilevante. Al contrario, se la funzione utilizza il modo tradizionale di passare gli argomenti, in questo caso invece
l’ordine dei parametri è rilevante.

Ciò a cui bisogna prestare un’attenzione particolare sono i valori di ritorno. Questi ultimi si differenziano a seconda che la
funzione restituisca il valore atteso o meno. Se la funzione ha successo, WordPress restituirà un valore (ad esempio un array
di oggetti), altrimenti può restituire un tipo di dati PHP (false, null ecc.) oppure un’istanza della classe WP_Error. Ad
esempio, prendiamo la funzione wp_remote_get():

$remote_file  = wp_remote_get( ‘http://sito/file.txt' );  


if( !is_wp_error( $remote_file  ) ) {  
// Successo!  
}

Invece, per la funzione wp_get_attachment_image_src() avremo:

$attachment_id  = 8;  
$image  = wp_get_attachment_image_src( $attachment_id  );  
if( $image  ) {  
// Successo!  
}

Questa funzione restituisce un array, quindi in questo caso la verifica da effettuare è diversa. Si consiglia quindi di leggere
sempre con attenzione gli esempi forniti nella documentazione. Si tratta di codice che illustra perfettamente i casi d’uso
delle funzioni o delle classi trattate.

Filtri  e  hook  

Due sono i tipi di hook che di solito useremo:

1. action  
2. filtri  

Le action vengono invocate durante un evento di WordPress, mentre i filtri servono a modificare l’output restituito dai
componenti dell’applicazione.

Questi hook hanno bisogno di una funzione o di un metodo di una classe che andremo a definire per poter operare. La
differenza tra i due sta nel fatto che un filtro ha bisogno di un input da modificare, mentre una action non presenta questa
necessità.

Ad esempio, se dovessimo applicare un nofollow a tutti i link di un post, dovremmo modificare l’output della funzione
the_content(). Il filtro corrispondente si chiama appunto the_content, quindi scriveremo:

function  add_nofollow( $content  ) {  


$content  = str_replace( ‘<a ‘, ‘<a rel=“nofollow” ‘, $content  );  
return  $content;  
}  
add_filter( ‘the_content', ‘add_nofollow'  );
Il nostro codice dovrà restituire sempre un valore: questa è la caratteristica dei filtri. Non è possibile fare altrimenti: se la
nostra funzione non avesse restituito il contenuto del post (modificato in questo caso), WordPress non avrebbe mostrato più
il contenuto dei post. Ovviamente possiamo usare la logica condizionale per filtrare l’input solo quando è necessario.

La nostra funzione in questo caso accetta un solo parametro, ossia il contenuto del post. Bisogna sempre leggere sulla
documentazione delle API quali parametri sono richiesti dalla funzione usata come filtro. Attenzione: se non usiamo i
parametri nel modo e nell’ordine corretto verrà restituito un errore. E molto spesso è solo un parametro quello che andremo
a modificare.

Le action, al contrario dei filtri, eseguono semplicemente del codice durante un evento di WordPress. Ad esempio, se
volessimo inserire il codice di Google Analytics nella sezione dei nostri documenti, dovremo usare l’action wp_head che è
direttamente collegata alla funzione wp_head(). Quindi scriveremo:

function  add_ga() {  
$ga_code  = ‘codice Analytics';  
echo  $ga_code;  
}  
add_action( ‘wp_head', ‘add_ga'  );

WordPress aggiunge il nostro codice alla serie di routine da eseguire in modo seriale e semplicemente lo esegue. Quello che
i filtri e le action hanno in comune, oltre al modo di associarli, è che possiamo spostare il sorgente avanti o indietro nella
coda di esecuzione di WordPress.

La documentazione:

• add_filter()  
• add_action()  

Il terzo parametro di entrambe le funzioni indica la priorità, ossia:

Lower  numbers  correspond  with  earlier  execution,  and  functions  with  the  same  priority  are  
executed  in  the  order  in  which  they  were  added(…).  

I numeri con un basso valore vengono eseguiti prima e le funzioni con la stessa priorità vengono eseguite nell’ordine in cui
sono state aggiunte.

Quindi, tornando al nostro filtro sul contenuto dei post, possiamo coordinare più routine in sequenza. La funzione che
avevamo definito viene eseguita con priorità 10, motivo per il quale se volessimo eseguire un’altra routine prima di questa:

function  my_previous_filter( $content  ) {  


// Routine  
return  $content;  
}  
add_filter( ‘the_content', ‘my_previous_filter', 5, 1 );

avremo che in questo caso la priorità è 5, quindi tale routine viene eseguita prima dell’altra. Come si può notare, leggere la
documentazione è il modo migliore di lavorare con WordPress.

Integrare API di terze parti nei plugin: Twitter


Twitter rappresenta un ottimo esempio di una piattaforma che fornisce API per l’interazione con i plugin di WordPress. In
questo capitolo vedremo come estrarre dati da Twitter utilizzando queste interfacce per la programmazione.
Le  API  di  Twitter  

Per descrivere il nostro progetto si può cominciare dal sito ufficiale per gli sviluppatori di Twitter. Quello che bisogna
capire da subito è che le API di Twitter funzionano solo tramite autenticazione. Occorre infatti creare un’app e ottenere
così le credenziali di accesso per poter usare le API (sezione “Keys and Access Tokens” di ogni app).

Un’app può avere diversi permessi: lettura, scrittura o entrambi. Un’app in sola lettura potrà leggere i tweet di un utente,
effettuare ricerche, visualizzare i trend del giorno ma non postare un tweet mentre, al contrario, un’app con permessi di
scrittura potrà effettuare anche quest’ultima operazione.

Ovviamente la pubblicazione dei tweet potrà avvenire unicamente tramite l’account Twitter che possiede l’app creata
attraverso di esso. Per gli esempi mostrati in questo capitolo sarà sufficiente un’app in sola lettura.

Librerie  PHP  per  Twitter  

L’approccio migliore per lavorare con le API è quello di utilizzare una libreria PHP esistente che andrà poi ad integrare
nella nostra implementazione.

Per Twitter possiamo usare la libreria TwitterOauth di Ricardo Pereira. Questa libreria supporta sia il metodo GET che
POST, quindi è adatta sia per app in lettura che in scrittura.

Reperire  i  tweet  da  Twitter  

Per reperire i tweet di un account Twitter dobbiamo utilizzare l’endpoint statuses/user_timeline delle API.
Creiamo una classe per questo scopo e per prima cosa includiamo la libreria TwitterOauth:

require_once( 'TwitterOauth.php'  );

Quindi definiamo la struttura della classe:

class  My_Twitter {  
private  $_connection;  
public  function  __construct() {  
$settings  = array(  
'oauth_token'  => 'tuotoken',  
'oauth_token_secret'  => 'tuotokensecret',  
'consumer_key'  => 'tuaconsumerkey',  
'consumer_secret'  => 'tuoconsumersecret',  
'output_format'  => 'text'  
);  
$this->_connection = new  TwitterOauth( $settings  );  
}  
//…  
}

Ora la proprietà privata _connection contiene un’istanza della classe TwitterOauth. A questo punto ci servono due
metodi privati per altrettanti compiti specifici:

1. formattare  le  date  di  Twitter  nel  formato  “…  fa”;  


2. trasformare  gli  hashtags  e  gli  URL  in  link  HTML.  

I metodi di riferimento saranno quindi i seguenti:


private  function  _relativeTime( $t  ) {  
$new_tweet_time  = strtotime( $t  );  
return  human_time_diff( $new_tweet_time, current_time( 'timestamp'  ) );  
}  
   
private  function  _format( $tweet  ) {  
$tweet_text  = $tweet->text;  
$tweet_entities  = array();  
   
foreach( $tweet->entities->urls as  $url  ) {  
$tweet_entities[] = array  (  
'type'        => 'url',  
'curText'  => substr( $tweet_text, $url->indices[0], ( $url->indices[1]
- $url->indices[0] ) ),  
'newText'  => '<a href=“'  . $url->expanded_url . '”>'  . $url->display_url
. '</a>'  
);  
}  
   
foreach  ( $tweet->entities->user_mentions as  $mention  ) {  
$string  = substr( $tweet_text, $mention->indices[0], ( $mention->indices[1] -
$mention->indices[0] ) );  
$tweet_entities[] = array  (  
'type'        => 'mention',  
'curText'  => substr( $tweet_text, $mention->indices[0], ( $mention-
>indices[1] - $mention->indices[0] ) ),  
'newText'  => '<a href=“https://twitter.com/'  . $mention->screen_name
. '”>'  . $string  . '</a>'  
);  
}  
   
foreach  ( $tweet->entities->hashtags as  $tag  ) {  
$string  = substr( $tweet_text, $tag->indices[0], ( $tag->indices[1] - $tag-
>indices[0] ) );  
$tweet_entities[] = array  (  
'type'        => 'hashtag',  
'curText'  => substr( $tweet_text, $tag->indices[0], ( $tag->indices[1]
- $tag->indices[0] ) ),  
'newText'  => '<a href=“https://twitter.com/search?q=%23'  . $tag-
>text . '&amp;src=hash”>'  . $string  . '</a>'  
);  
}  
   
foreach  ( $tweet_entities  as  $entity  ) {  
$tweet_text  = str_replace( $entity['curText'], $entity['newText'], $tweet_text  
);  
}  
   
return  $tweet_text;  
}

Ora dobbiamo definire il metodo principale, stavolta pubblico, per reperire i tweet utilizzando il metodo
TwitterOauth::get():

public  function  fetch() {  


$params  = array(  
'screen_name'  => 'gabromanato',  
'count'  => 3,  
'exclude_replies'  => true  
);  
   
$html  = '<div id=“twitter-feed”>';  
   
$resp  = $this->_connection->get( 'statuses/user_timeline', $params  );  
$tweets  = json_decode( $resp  );  
   
foreach( $tweets  as  $tweet  ) {  
$html  .= '<div class=“tweet”>';  
$html  .= '<time class=“tweet-date”>'  . $this->_relativeTime( $tweet-
>created_at ) . '</time>';  
$html  .= '<div class=“tweet-body”>'  . $this->_format( $tweet  ) . '</div>';  
$html  .= '</div>';  
}  
   
$html  .= '</div>';  
return  $html;  
}

Seguendo il design di WordPress, concluderemo la nostra implementazione definendo una funzione che utilizzerà la classe
appena creata, impedendo così che una classe venga usata direttamente.

C’è un potenziale problema di performance nel nostro codice: troppe richieste GET potrebbero rappresentare un bottleneck
per un sito. Fortunatamente WordPress dispone delle Transients API che ci permettono di creare un sistema di caching di
durata personalizzabile. Quindi scriveremo:

require_once( 'My_Twitter.php'  );  


function  my_get_tweets( $echo  = false ) {  
   
$html  = '';  
if  ( false === ( $feed  = get_transient( 'my-tweets'  ) ) ) {  
$twitter_getter  = new  My_Twitter();  
$html  = $twitter_getter->fetch();  
set_transient( 'my-tweets', $html, 5 * MINUTE_IN_SECONDS );  
} else  {  
$html  = get_transient( 'my-tweets'  );  
}  
if( $echo  ) {  
echo  $html;  
} else  {  
return  $html;  
}  
}

Nel caso specifico dell’esempio proposto il codice metterà in cache per 5 minuti i risultati ottenuti da Twitter, solo dopo
questo intervallo di tempo verrà effettuata nuovamente una richiesta GET.

Integrare i plugin di WordPress con i Web


services
WordPress può interagire facilmente con i Web services messi a disposizione dalle varie piattaforme. In questo articolo
vedremo come implementare un esempio di tale integrazione nei plugin.

Come  funziona  un  Web  service  

Un Web service funziona mediante un’architettura client-server. L’utente effettua una richiesta lato client e il server remoto
esegue un’azione restituendo solitamente un output che informa sull’esito dell’azione oppure fornisce dei dati che sono stati
richiesti.

Solitamente i metodi HTTP utilizzati in questi casi sono GET e POST. Un Web service può anche scegliere di far eseguire
le sue azioni solo tramite POST se il suo design è concepito in tale modo.

Per esempio, per inserire un file su Amazon S3 effettueremo una richiesta e il Web service ci comunicherà se il
trasferimento ha avuto successo. Come avviene tutto questo? Tramite le API, interfacce per la programmazione messe a
disposizione dal Web service di cui dovremmo studiare esempi e documentazione ed eventualmente scaricare un SDK per
lo sviluppo in PHP.

Quando si usa un Software Development Kit occorre verificare la compatibilità con la versione di PHP in uso sul server,
infatti, alcune feature potrebbero funzionare solo da una determinata versione del linguaggio in poi, come accade per i
namespace introdotti soltanto con la release 5.3 di PHP.

Usare  le  API  di  Amazon  per  reperire  informazioni  sui  prodotti  

Possiamo usare le API AWS (Amazon Advertising API) per reperire informazioni relative ai prodotti presenti nel catalogo
del noto sito Web per il commercio elettronico; per far questo occorrono però le credenziali di accesso alle API.

Quindi, per prima cosa definiamo una funzione per effettuare la richiesta. Ci serviranno anche i dati relativi al codice ASIN
(Amazon Standard Identification Number) del prodotto e alla regione di riferimento.

function  my_aws_signed_request( $region, $params  ) {  


   
$public_key  = "chiave pubblica";  
$private_key  = "chiave privata";  
   
$method  = "GET";  
$host  = "ecs.amazonaws."  . $region;  
$host  = "webservices.amazon."  . $region;  
$uri  = "/onca/xml";  
   
$params["Service"] = "AWSECommerceService";  
$params["AssociateTag"] = "affiliate-20"; // Il vostro codice Affiliate  
$params["AWSAccessKeyId"] = $public_key;  
$params["Timestamp"] = gmdate( "Y-m-d\TH:i:s\Z"  );  
$params["Version"] = "2015-06-20";  
   
ksort( $params  );  
   
$canonicalized_query  = array();  
   
// Prepariamo la query con i parametri passati  
   
foreach  ( $params  as  $param  => $value  ) {  
$param  = str_replace( "%7E", "~", rawurlencode( $param  ) );  
$value  = str_replace("%7E", "~", rawurlencode( $value  ) );  
$canonicalized_query[] = $param  . "="  . $value;  
}  
   
$canonicalized_query  = implode( "&", $canonicalized_query  );  
   
$string_to_sign  = $method  . "\n"  . $host  . "\n"  . $uri  . "\n"  .
$canonicalized_query;  
   
// Prepariamo la firma (signature)  
   
$signature  = base64_encode( hash_hmac( "sha256", $string_to_sign, $private_key,
true ) );  
$signature  = str_replace( "%7E", "~", rawurlencode( $signature  ) );  
   
$request  = "http://"  . $host  . $uri  . "?"  . $canonicalized_query  . "&Signature="  
. $signature;  
$response  = wp_remote_get( $request  );  
   
if( !is_wp_error( $response  ) ) {  
   
$pxml  = @simplexml_load_string( $response["body"] );  
   
if  ( $pxml  === false ) {  
return  false;  
} else  {  
return  $pxml;  
}  
} else  {  
return  false;  
}  
}

Amazon restituisce una risposta in formato XML, dobbiamo quindi effettuare il parsing del documento XML restituito:

function  my_aws_get_product_info( $region, $asin  ) {  


   
$xml  = my_aws_signed_request( $region, array(  
"Operation"  => "ItemLookup", // Richiediamo informazioni  
"ItemId"  => $asin, // Codice ASIN  
"IncludeReviewsSummary"  => false, // Nessuna recensione  
"ResponseGroup"  => "Medium,OfferSummary"  // Informazioni di base  
));  
   
$info  = null;  
   
$item  = $xml->Items->Item;  
   
$title  = htmlentities( ( string ) $item->ItemAttributes->Title );  
$url  = htmlentities( ( string ) $item->DetailPageURL );  
$image  = htmlentities( ( string ) $item->MediumImage->URL );  
$price  = htmlentities( ( string ) $item->OfferSummary->LowestNewPrice->Amount
);  
$code  = htmlentities( ( string ) $item->OfferSummary->LowestNewPrice-
>CurrencyCode );  
$qty  = htmlentities( ( string ) $item->OfferSummary->TotalNew );  
   
if  ( $qty  !== "0"  ) { // Solo se il prodotto è disponibile  
$info  = array(  
"code"  => $code,  
"price"  => number_format( ( float ) ( $price  / 100 ), 2, '.', ''  ),  
"image"  => $image,  
"url"  => $url,  
"title"  => $title  
);  
}  
   
return  $info;  
}

Abbiamo così ottenuto il titolo del prodotto, l’URL della sua pagina, l’URL della sua immagine, il prezzo, la valuta e la
quantità; la funzione scritta potrà essere utilizzata in questo modo:

$product_info  = my_aws_get_product_info( "com", "B00KQPGRRE"  );  


if( !is_null( $product_info  ) ) {  
//...  
}

Advanced Custom Fields: campi personalizzati


per gli sviluppatori WordPress
Advanced Custom Fields è un plugin per WordPress sviluppato da Eliott Condon indirizzato principalmente agli
sviluppatori di temi per WordPress.

Lo scopo di ACF, che è possibile scaricare ed installare facilmente con la procedura standard adottata della stragrande
maggioranza dei plugin, è quella di rendere disponibile un’interfaccia grafica chiara e flessibile nel backend del CMS per
gestire campi personalizzati per tutte le tipologie di custom post type, di tassonomie, di file multimediali e di utenti.

Una  volta  scaricato  ed  attivato,  il  plugin  (in  gran  parte  tradotto  in  italiano)  inserisce  una  nuova  
voce  nel  menu  amministrativo  che  comprende  la  pagina  per  la  gestione  dei  campi,  una  pagina  
dedicata  all’esportazione  e  un’altra  per  l’installazione  dei  componenti  aggiuntivi.    

Creare  i  campi  

Creare un nuovo campo è molto semplice: i campi sono raccolti per gruppi che si creano tramite la familiare interfaccia di
WordPress. Creato un gruppo, al suo interno possono essere inseriti tutti i campi desiderati. La reale forza del plugin risulta
evidente proprio in questa fase: le tipologie di campo disponibili sono molte, dalle più semplici come i campi di testo, ai
campi con validazione per numeri e indirizzi email, fino a elementi con GUI più complesse quali caricamento di immagini,
relazione fra post type tramite AJAX, date picker e color picker.

Figura 1. Le tipologie di campi disponibili.


 
La prima operazione da compiere è quella di dare un nome al campo. In base a questo nome ACF creerà anche uno slug
(denominato “nome del campo”) privo di tutti i caratteri non consentiti nel codice che ci verrà proposto alla linea successiva
(ma che potremo sempre modificare). Tramite un menu a tendina potremo scegliere la tipologia di campo, questa scelta
determinerà anche quali voci dovremo compilare successivamente: oltre alle possibilità, sempre presenti, di aggiungere una
spiegazione per la compilazione e di renderlo obbligatorio; le opzioni necessarie per poterlo effettivamente utilizzare
verrano caricate in modo asincrono.

Ad esempio, per l’inserimento di un menu a tendina dovremo elencare le coppie valore/etichetta e il valore di default; per
campi di relazione dovremo specificare quale tipologia di elemento deve essere possibile relazionare, mentre per le
immagini dovremo specificare la grandezza delle anteprime e, soprattutto, se desideriamo come valore restituito la ID
dell’immagine, la sua URL o un oggetto PHP con le sue proprietà.

Il secondo passo è quello di indicare a quali tipologie di oggetti di WordPress va allegato questo gruppo di campi. È
possibile combinare più regole che indicano il post type, le pagine (anche per un singolo template), il ruolo dell’utente, il
tipo di tassonomia, o i media files. Questo semplifica di molto il lavoro dello sviluppatore, che non dovrà più preoccuparsi
di inserire tutto il codice necessario per aggiungere i campi per ciascuna delle diverse tipologie di contenuti.

Figura 2. Le regole di assegnazione di un gruppo di campi.

 
La parte amministrativa dei campi può essere personalizzata facilmente stabilendone l’ordine con un immediato drag and
drop e raggruppandoli tramite un capo specifico denominato tab. Nel backend verrano inclusi tutti i campi con i relativi file
JavaScript e CSS necessari alla loro GUI.

In questo esempio abbiamo creato 7 campi, di cui due in realtà semplici tab che non restituiscono un valore, ma che aiutano
a personalizzare l’area amministrativa.

Figura 3. Esempio di gruppo con sette campi inseriti.


 
Questo è il risultato finale che ci si presenta quando apriamo un post, una pagina, o un altro tipo di contenuto al quale
abbiamo associato i campi.

Figura 4. Risultato nel backend.


 
 

Richiamare  i  campi  nel  tema  

Fino a questo punto il plugin è utilizzabile via interfaccia grafica, ma per richiamare in un tema i valori dei campi
personalizzati, a meno di non appoggiarsi ad altri plugin, dobbiamo lavorare sul codice.

L’esempio base è molto semplice: i due metodi fondamentali sono the_field() e get_field(). Il primo stampa a
schermo il valore del campo, il secondo lo legge e lo rende disponibile per successive elaborazioni. La sintassi è la
seguente:

<?php  
if( get_field( "nome_campo"  ) ) { ?>  
<p><?php the_field( "nome_campo"  ); ?></p>  
<?php } ?>

Nella prima riga controlliamo l’esistenza del campo e che il valore non sia nullo, nella seconda riga lo stampiamo a
schermo. Per entrambi i metodi l’unico parametro obbligatorio è lo slug del campo; se siamo all’interno di un loop di
WordPress il metodo si riferirà automaticamente al post che viene elaborato, diversamente possiamo passare come secondo
parametro l’id del post che ci interessa, oppure della tassonomia o dell’utente tramite le diciture: category_1 e user_1,
dove nella prima parte della stringa indichiamo lo slug della tassonomia (o “user” per gli utenti) e subito dopo l’underscore
l’id vero e proprio.

Nel caso delle immagini o dei file caricati, il codice cambia a seconda dell’opzione da noi selezionata sul valore restituito.
Sicuramente scegliere l’oggetto PHP ci dà una maggiore flessibilità. Ecco un esempio:

<?php  
$immagine  = get_field('immagine');  
/*La variabile immagine ha questo valore:  
Array  
(  
[id] => 540  
[alt] => Testo alternativo  
[title] => Titolo dell’immagine  
=> Didascalia dell’immagine  
[description] => Descrizione dell’immagine  
[url] => http://localhost:8888/acf/wp-
content/uploads/2013/09/imm.jpg  
[sizes] => Array  
(  
[thumbnail] => http://localhost:8888/acf/wp-
content/uploads/2013/09/imm-150x150.jpg  
[medium] => http://localhost:8888/acf/wp-
content/uploads/2013/09/imm-300x119.jpg  
[large] => http://localhost:8888/acf/wp-
content/uploads/2013/09/imm.jpg  
)  
)  
Stampa dell’immagine alla dimensione "large" */  
?>  
<img src="<?php echo $immagine['sizes']['large']; ?>"  alt="<?php echo
$immagine['alt']; ?>"  />

In tutti quei campi nei quali sono previsti più valori viene restituito un array. Nel caso si tratti del tipo di campo di tipo
“relazione” si posso ottenere come valori di ritorno gli id dei post, oppure direttamente dei post object che possono
inizializzare la funzione setup_postdata() per generare dei loop, come in questo esempio, nel quale viene creato un elenco di
post con permalink e titolo.

<?php  
$post_objects  = get_field('relazione');  
if( $post_objects  ): ?  
<ul>  
<?php foreach( $post_objects  as  $post): /*La variabile deve essere chiamata
$post */  ?>  
<?php setup_postdata($post); ?>  
<li>  
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>  
</li>  
<?php endforeach; ?>  
</ul>  
<?php wp_reset_postdata(); /*Questo reset è obbligatorio per la corretta
esecuzione dei loop successivi */  ?>  
<?php endif; ?>

Estendere  le  funzionalità  di  Advanced  Custom  Fields  

Con queste operazioni di base si possono ottenere rapidamente interfacce complesse dotate di funzionalità decisamente più
avanzate di un’installazione standard di WordPress, ma ACF può offrire molto di più.

Dal punto di vista dello sviluppo il componente offre numerosi hook e filter e dà la possibilità agli sviluppatori di creare i
propri campi aggiuntivi che possono essere installati come normali plugin di WordPress. Campi per form, per mappe, per
orari e per sistemi di pagamento sono solo alcuni esempi presentati nel sito ufficiale, dal quale si possono anche acquistare
componenti aggiuntivi a pagamento (con licenza multisite) per le gallerie di immagini, pagine di impostazioni
personalizzate, campi ripetibili e layout personalizzabili. Lo sviluppatore mette a disposizione su GitHub un template di
partenza per costruire i propri campi.
Allo stesso tempo avere a disposizione le API del componente rende possibile costruire un form con i campi personalizzati,
comprensivi di interfaccia utente, anche nel frontend, come mostra questo template:

<?php  
/**  
* Template Name: Pagina con form per campi personalizzati  
* Un page template personalizzato con i campi creati da ACF  
*/  
acf_form_head(); /* Questa funzione include tutti i file CSS e JavaScript necessari
all’interfaccia dei campi personalizzati. Deve essere inclusa prima di
get_header(). */  
get_header();  
?>  
<?php the_post(); ?>  
<?php  
//Opzioni per l’inclusione del form  
$options  = array(  
'post_id'  => $post->ID, /* post id del post type cui sono assegnati i
campi*/  
'field_groups'  => array(), /* id del gruppo di campi. Se vuoto inserirà
tutti quelli realivi a quel post id*/  
'form'  => true, // Aggunge il tag "form"  
'form_attributes'  => array( // Attributi del form  
'id'  => 'post',  
'class'  => '',  
'action'  => '',  
'method'  => 'post',  
),  
'return'  => add_query_arg( 'updated', 'true', get_permalink() ), /* url di
ritorno. L'argomento "updated" fa visualizzare il messaggio di conferma*/  
'html_before_fields'  => '', /* html da inserire prima dei campi*/  
'html_after_fields'  => '', /* html da inserire dopo i campi */  
'submit_value'  => 'Aggiorna', /* valore del pulsante di submit */  
'updated_message'  => 'Post aggiornato.', /* Messaggio di conferma */  
); ?  
<?php acf_form( $options  ); // Questa è la funzione che genera il form ?>  
   
<?php get_sidebar(); ?>  
<?php get_footer(); ?>

In sintesi, la funzione acf_form() genera il form con tutti i campi compresi nel gruppo specificato tramite il suo id (ogni
gruppo di campi è in realtà un custom post type); è suffciente che nella head della pagina siano stati caricati tutti i file
necessari tramite la funzione acf_form_head().

Conclusioni  

Sicuramente Advanced Custom Fields, è uno degli strumenti più completi per la gestione dei campi personalizzati in
WordPress e può rendere molto più rapido lo sviluppo in tutti quei casi nei quali è prevista l’implementazione di diversi
campi personalizzati anche complessi, che da soli richiederebbero una programmazione aggiuntiva piuttosto impegnativa
per la gestione dell’ di interfaccia utente.

Creare un sito WordPress multilingua permette di ampliare la tua attività, di attirare un volume di traffico decisamente
più corpulento e naturalmente di aumentare i guadagni. Che si tratti di un sito vetrina o di un ecommerce i vantaggi sono
tantissimi.
Per farla breve: si tratta di una scelta con un potenziale inimmaginabile che potrebbe aprire nuove porte al tuo
business. Grazie ad un sito WordPress multilingua puoi cominciare a ricevere traffico in diverse lingue e da diversi paesi
del mondo e riuscire così ad aumentare le tue vendite ed i tuoi guadagni online.

Abbiamo capito che creare e gestire uno spazio online multilingua su WordPress è un’ottima idea, ma come succede sempre
in questi casi, dopo il primo entusiasmo subentra il panico da “e ora da dove comincio?”.

Per fortuna conosco e so utilizzare il migliore plugin WordPress multilungua: WPML!

Di seguito puoi leggere la mia guida dettagliata. Sono circa 5000 parole, quindi preparati perché abbiamo un bel po di cose
da vedere.

Creare  un  sito  WordPress  multilingua  con  WPML  

WPML è il plugin WordPress multilingua che ti aiuta a creare un sito web traducibile in diverse lingue. Più
precisamente, permette di generare copie delle pagine, degli articoli, dei menu e di tutti gli altri contenuti testuali del tuo sito
web in altre lingue a tua scelta. E non si ferma qui. WPML offre anche un ampio ventaglio di impostazioni di
configurazione per decidere come visualizzare le opzioni di lingua sul sito web interessato.

Quello che lo rende davvero raccomandabile è la sua straordinaria compatibilità con WordPress e tutto ciò che ruota
attorno a questa piattaforma: dai temi agli altri plugin. Non per niente WPML è generalmente considerato lo standard per
creare siti web WordPress multilingua.

Sebbene WPML renda questo processo decisamente più semplice rispetto ad altre strade, un aiuto extra non fa mai male,
soprattutto perché non tutto il manuale di WPML è disponibile in italiano (ironico, lo so). Ecco perché ti spiegherò passo
per passo come fare a installarlo e ad utilizzarlo per rendere il tuo sito multilingua.

L’obiettivo di questa guida è rendere il più chiaro possibile come creare e gestire un sito web multilingua su WordPress con
WPML. Non vogliamo dunque fare di tutta l’erba un fascio. Per questo e per tua comodità, analizzeremo separatamente
come creare un sito vetrina multilingua e come creare un ecommerce multilingua usando WPML.

Partiamo prima di tutto dalla base.

Installare  il  plugin  WPML  su  WordPress  

Per creare una piattaforma multilingua su WordPress la prima cosa da fare è installare WPML come un normalissimo
plugin. Ciò significa che devi andare sulla pagina dei plugin di WordPress, scaricare e avviare l’installazione di WPML.

Come avrai notato WPML è un plugin a pagamento e ha un prezzo che varia a seconda delle opzioni e della durata del
contratto. In particolare puoi acquistare tre pacchetti di WPML:
• 29  $  licenza  per  un  anno  e  siti  illimitati:  è  l’offerta  studiata  per  i  blog  multilingua.  
• 79  $  licenza  per  un  anno  e  siti  illimitati:  per  creare  uno  sito  web  multilingua,  ovvero  con  la  
possibilità  di  tradurre  anche  temi  e  plugin  (quello  che  interessa  a  noi).  
• 195  $  per  sempre  e  siti  illimitati:  in  questo  modo  non  dovrai  più  preoccuparti  del  
rinnovamento.  

Fidati: di tutti i plugin e le funzionalità per il tuo sito web che puoi trovare free, la funzione multilingua è l’ultima su cui
puoi fare economia. Non solo perché quelli di WPML sono soldi ben spesi, ma anche (e soprattutto) perché quando devi
creare un sito multilingua su WordPress la qualità è fondamentale. Pensa a che disastro succederebbe nel caso che le
traduzioni dei tuoi testi e dei tuoi menu fossero sbagliate o imprecise.

Acquista dunque l’offerta che fa maggiormente al caso tuo.

Configurare  WPML  e  scegliere  le  lingue  in  cui  tradurre  il  tuo  sito  web  

Una volta scaricato e installato il plugin, nella tua bacheca di WordPress clicca a sinistra su WPML per entrare nel Setup
(ovvero le impostazioni generali del plugin).

Innanzitutto è necessario impostare la lingua sorgente del tuo sito web, ovvero la lingua in cui sono scritti attualmente i
tuoi contenuti. Nel tuo caso verosimilmente sarà Italiano, ma puoi decidere in ogni momento di aggiungere o togliere una
lingua, o invertire il loro ordine.

Nella pagina successiva trovi un elenco di lingue “flaggabili” tra cui scegliere. Si tratta del cuore del plugin, ovvero, dove
succede tutta la “magia” della traduzione istantanea dei tuoi contenuti. Qui devi selezionare le lingue in cui hai intenzione di
tradurre i testi, ovvero le altre lingue in cui il tuo sito web sarà leggibile e visualizzabile.

La scelta è vastissima e puoi optare per le lingue più disparate, dal cinese allo spagnolo. Questo è un altro punto di forza di
WPML quando si tratta di creare un ambiente web multilingua su WordPress.

L’ultima pagina delle impostazioni permette di gestire le funzionalità di WPML. Puoi scegliere:

• l’ordine  delle  lingue  scelte,  che  funziona  con  un  semplice  drag  and  drop.  
• in  che  modo  organizzare  le  opzioni  di  lingua  tra  menu  a  tendina,  pulsante  classico  o  
elenco.  Per  aiutarti  a  scegliere  è  persino  disponibile  un’anteprima  sulla  destra.  
• come  visualizzare  le  lingue  (bandiera  o  parola).  
• qui  ti  è  data  la  possibilità  di  decidere  anche  come  WPML  deve  comportarsi  con  le  pagine  o  
i  contenuti  che  non  può  tradurre.  
Quando hai finito di scegliere e sistemare le voci delle impostazioni che ti interessano, salva.

Adesso nella bacheca, sotto la voce WPML appaiono nuove voci. Tra le nuove impostazioni più importanti, puoi per
esempio scegliere il formato URL delle pagine tradotte.

Creare  un  “sito  vetrina”  multilingua  con  WPML  

Iniziamo a vedere come creare un sito vetrina multilingua con WPML. Così tutti i tuoi contenuti saranno disponibili
anche in altre lingue, risultando comprensibili – e invitanti – anche per gli utenti stranieri.

Con sito vetrina si intende un normale portale web costituito da pagine, contenuti testuali, immagini e video. Per esempio, il
sito web di un’azienda, con la classica gerarchia pagine del “chi siamo”, “prodotti”, “blog” e “contatti”.

Il tuo sito vetrina può contenere dei plugin e widget, ma non la funzione ecommerce. Come già anticipato, questo è un caso
a parte che merita di essere analizzato più avanti.

Creare  articoli  multilingua  

Riprendiamo da dove avevamo lasciato, ovvero dalla configurazione di WPML. Una volta confermate le impostazioni,
possiamo iniziare a creare una piattaforma web multilingua su WordPress.

Partiamo dal contenuto vero e proprio: gli articoli. Clicca su Articoli dalla tua bacheca WordPress.

Noterai che adesso appare un nuovo menu in alto che mostra le lingue che hai scelto nelle impostazioni di WPML. Non
solo, per ogni opzione indica gli articoli pubblicati in ciascuna delle lingue scelte nelle impostazioni, come in questa
immagine sotto:
Cliccando su ogni lingua appare l’elenco dei post tradotti. Lateralmente ai titoli compare una nuova colonna, con una
bandiera in cima e delle icone di un più. La bandiera indica quella che hai scelto come prima lingua straniera di default. Il
simbolo “+” serve per creare la copia di ciascun articolo direttamente nella lingua di default (appunto quella indicata dalla
bandiera). Ma vediamo nel dettaglio come.

Per tradurre un articolo di WordPress in un’altra lingua con WPML ci sono due modi.

1. Se  vuoi  creare  una  copia  dell’articolo  nella  lingua  impostata  come  default  clicca  sul  più  
(+).  A  questo  punto  si  aprirà  una  pagina  in  cui  puoi  inserire  manualmente  il  contenuto  
tradotto.  Puoi  anche  scegliere  di  duplicare  quello  già  esistente  nella  lingua  sorgente,  così  
da  poter  conservare  elementi  come  immagini  e  video,  sovrascrivendo  solo  la  parte  
testuale.  

2. Altrimenti,  modifica  l’articolo  desiderato.  Sulla  destra  puoi  scegliere  in  che  lingua  tradurre  
l’articolo  e  decidere  se  duplicare  il  contenuto  della  lingua  originaria  (vedi  sopra).  

Per confermare clicca su Pubblica.

Fatto questo, nel menu degli articoli vedrai l’icona di una matita dove prima c’era il più. Questo indica quali articoli sono
stati già tradotti.

Creare  pagine  multilingua  

Veniamo adesso come tradurre le pagine.

Il procedimento per creare delle pagine multilingua su WordPress è pressoché lo stesso usato per gli articoli. Anche in
questo caso possiamo cliccare sull’icona del “+” oppure su Modifica.

Importante: nel pannello di modifica noterai come l’URL della pagina è diverso a seconda della lingua, di cui contiene la
sigla. Per modificare il formato URL delle pagine multilingua basta andare nelle impostazioni Lingue di WPML dalla
bacheca, come spiegato precedentemente.

Ancora una volta, per confermare clicca su Pubblica.

Senza saperlo sei già riuscito ad ottenere un sito tradotto con WPML, almeno parzialmente.

Visualizza il tuo sito web per renderti conto di quanto fatto. Nelle pagine che hai tradotto puoi vedere il menu con le lingue
disponibili tra cui scegliere per visionare la rispettiva pagina appena creata.

Cliccando invece su un articolo, alla fine del testo viene segnalato automaticamente in quali altre lingue tale contenuto è
disponibile, con la possibilità anche in questo caso di cliccare su quella desiderata.

Scegliendo una lingua dall’elenco, il sito web cambia automaticamente, caricando le copie multilingue che hai creato, sia
delle pagine che degli articoli.
Infine, noterai che alcuni elementi della pagina sono stati tradotti automaticamente nella lingua selezionata, come ad
esempio le categorie e il nome stesso delle lingue.

Tradurre  il  menu  di  un  sito  web  WordPress  con  WPML  

Quello che invece non è cambiato pur selezionando un’altra lingua è il menu di navigazione. Non preoccuparti, è normale.
Infatti per creare un menu di navigazione multilingua occorre seguire un procedimento a sé. Vediamo come.

Vai nella tua bacheca WordPress e da Aspetto seleziona la voce Menu.

Ti ritrovi nella classica pagina di gestione dei tuoi menu di navigazione. Con una piccola differenza, perché anche qui
adesso compare l’opzione lingua.

A destra scegli il menu che vuoi tradurre e seleziona la lingua di destinazione. Ora puoi creare la versione in un’altra lingua
del tuo menu, conservando tutte le caratteristiche del menu originario (gerarchia pagine e così via).

Come puoi vedere WPML rende questo processo molto intuitivo e bastano pochi passaggi per familiarizzare con l’intero
funzionamento del plugin. Lavorare con WPML infatti è facile persino per i principianti.

A questo punto hai tradotto tutto il contenuto del tuo sito web. Dagli articoli alle pagine, fino al menu di navigazione. Tutti
questi elementi cambiano lingua nel momento in cui i visitatori ne selezionano una diversa dal menu che appare su ciascuna
pagina web tradotta.

Eppure come ben sai un sito web è fatto anche da altri elementi, primi fra tutti i plugin e i widget. Ebbene, è possibile
tradurre plugin e widget usando WPML, così da creare un sito multilingua su WordPress a 360 gradi. Abbi solo ancora
un po’ di pazienza, ci arriviamo subito.
Creare  un  “sito  e-­‐Commerce  Multilingua”  con  WPML  

Questa parte della guida è rivolta ai lettori che vogliono creare un sito e-commerce multilingua su WordPress con
WPML per vendere dei prodotti.

Capita spesso – per nostra grande fortuna – che l’amatissimo Made in Italy spopoli all’estero. Infatti, in alcuni casi è
proprio il mercato internazionale a fare la fortuna di un brand. Aziende italiane, medie e persino piccole, si trovano così a
doversi equipaggiare per vendere anche fuori del nostro paese.

WPML ti permette di realizzare anche questo compito in modo facile. Vediamo subito come.

Il primo requisito fondamentale per creare un ecommerce su WordPress è munirsi di un plugin che svolga questa funzione.
Ne esistono diversi, ecco una lista dei migliori plugin ecommerce gratuiti per WordPress. Nel nostro caso ipotizziamo di
aver installato il popolare plugin ecommerce per WordPress WooCommerce.

Ma  come  creare  questo  e-­‐commerce  multilingua  in  modo  semplice?  

Hai installato un plugin ecommerce per WordPress e il plugin multilingua WPML (se non l’hai fatto, è il caso che tu faccia
qualche passo indietro in questa guida). Adesso è il momento di creare il tuo ecommerce multilingua su WordPress con
WPML.

Per quanto riguarda creare pagine e articoli multilingue, il processo è lo stesso spiegato qui sopra, nella parte relativa alla
creazione di un sito web vetrina multilingua. Ora però vogliamo vedere come tradurre i componenti e le pagine tipiche di un
ecommerce, prime fra tutti le schede prodotto.
Tradurre  i  prodotti  

Regola numero 1 per un ecommerce multilingua di successo: tradurre i prodotti correttamente. In fin dei conti è questo il
fulcro di un ecommerce e quindi merita un trattamento speciale.

I clienti che visitano il tuo sito web devono essere in grado di:

1. capire  esattamente  quello  che  stanno  acquistando,  


2. avere  chiaro  ogni  dettaglio  dell’acquisto.  

Ogni volta che un utente compra un tuo prodotto stai stipulando un contratto. Essere chiaro nella descrizione, nelle
condizioni di vendita e nelle modalità di pagamento è fondamentale per evitare una lunga serie di richieste di rimborso,
oltre naturalmente per salvaguardare la tua reputazione.

Per tua fortuna tradurre i prodotti di un ecommerce multilingua con WPML è molto semplice.

Nel caso di un ecommerce è importante tradurre tutte le pagine non solo del sito web stesso, ma anche del processo di
acquisto, incluse le schermate del carrello e del checkout.

Non devi fare altro che andare in Pagine sulla bacheca di WordPress e creare la copia multilingua di tutte le pagine
dell’ecommerce, come già visto sopra con una normalissima pagina web. Grazie a WPML puoi tradurre ogni aspetto o
definizione legata al tuo commercio, come ad esempio il termine “size” o “color” riferito ai prodotti in vendita.

Una volta installato un plugin ecommerce per WordPress (nel nostro caso WooCommerce) tra le voci a sinistra della
bacheca compare infatti anche la voce Prodotti.
Clicca qui. Si aprirà la lista di tutti i prodotti pubblicati sul tuo sito web, proprio come succede con gli articoli di un blog. In
alto a questa pagina puoi vedere l’elenco delle lingue selezionate nelle impostazioni di WPML.

Seleziona il prodotto che vuoi tradurre e a destra delle pagina di modifica clicca su Duplica.

Adesso che hai la copia multilingua della pagina del prodotto, a destra sotto Lingue puoi vedere la lingua in cui è
visualizzato il prodotto sul sito web e la lingua della traduzione. Clicca sull’icona della matita per modificare il contenuto.

Scrivi o incolla il testo nella nuova lingua, ricordandoti di sostituire correttamente tutti gli elementi testuali della
pagina: dal titolo alla descrizione.

In questa pagina (sempre a destra) puoi anche caricare una nuova immagine, in caso quella originaria contenga del testo
in italiano. Basta cliccare e scegliere l’immagine. Molto importante: in questa sezione ricorda di tradurre il titolo e la
descrizione dell’immagine.

Salva.

Finalmente puoi cambiare lingua anche nella pagina del prodotto. Visualizza il sito web in un’altra lingua e apri un prodotto
per vedere la pagina tradotta. Noterai che WPML traduce automaticamente i pulsanti di acquisto (come “aggiungi al
carrello”). Decisamente una bella sorpresa.

Eppure manca ancora qualcosa.

Convertire  la  valuta  su  un  ecommerce  multilingua  di  WordPress  con  WPML  

Certo, i tuoi clienti devono capire cosa vendi, ma anche quanto costa. Per questo nel creare un ecommerce multilingua su
WordPress con WPML devi anche inserire tutte le valute straniere che ti interessano, in relazione alle lingue previste.

Nel caso di WooCommerce, è possibile impostare una valuta di default per ciascuna lingua specifica. In questo modo,
quando un visitatore cambia lingua (per esempio Giapponese) il sito web cambia automaticamente valuta (Yen).

Esistono due modi per prezzare i tue prodotti in multi valuta:

• manualmente:  sei  tu  a  inserire  il  prezzo  di  un  prodotto  nella  valuta  straniera.  

• automaticamente:  quando  viene  selezionata  una  valuta  diversa  da  quella  di  default,  il  
plugin  cambia  automaticamente  i  prezzi,  aggiornandoli  in  base  ai  tassi  di  cambio  
impostati.  

Puoi scegliere una delle due opzioni dalle impostazioni del plugin. Vediamo bene come.

Innanzitutto devi attivare il plugin WPML Translation Management. Si tratta di un altro strumento importante per
ottimizzare la procedura delle traduzioni.

Dalla tua bacheca di WordPress vai con il cursore su WPML per fare apparire un elenco di opzioni del plugin. Clicca su
WooComerce Multilingual.

Qui puoi attivare la multi valuta e scegliere se impostare la valuta del tuo ecommerce multilingua automaticamente o
manualmente.
Dopo avere salvato la tua scelta compare l’opzione per aggiungere una valuta straniera. Qui devi scegliere la lingua da
attribuire alla valuta, il codice (o abbreviazione, per esempio EUR nel caso di euro, USD per il dollaro, ecc.) e il tasso di
cambio attuale.

NB: Nel caso di un sito italiano, creando la valuta euro bisogna impostare 0 come tasso di cambio.

Se invece decidi di impostare i prezzi manualmente, dovrai inserirli per ciascun prodotto. Si tratta di una scelta più
scomoda, che ha senso solo in circostanze particolari.

Ce l’abbiamo fatta. Siamo riusciti a creare un sito ecommerce multilingua su WordPress con WPML. Visita il tuo sito web e
apri una scheda prodotto. Adesso puoi cambiare lingua e valuta.

Tradurre  i  widget,  i  plugin  e  i  temi  con  WPML  

Adesso è arrivato il momento di tradurre anche tutti quegli elementi del sito web che fanno da contorno ai contenuti: i
widget, i plugin e naturalmente il tema in uso.

Vediamo come fare.

Tradurre  i  widget  con  WPML  

Su WordPress l’uso di widget è pratica comune. Molti di questi contribuiscono in modo diretto alla qualità dell’esperienza
degli utenti sul sito web. Tuttavia quando si decide di creare un sito web multilingue su WordPress con WPML, i widget
installati non vengono tradotti in automatico (come succede per altri aspetti come le categorie).

Ne risulta l’effetto opposto: quello che prima era un aiuto si trasforma in un fattore disturbante. Per fortuna il nostro plugin
multilingua per WordPress WPML non ci delude nemmeno questa volta.

Se stai usando i widget di default di WordPress oppure widget non di default ma comunque codificati correttamente,
WPML permette di tradurre sia il titolo che il contenuto del widget.

WPML permette di gestire in Traduzione stringhe la traduzione dei titoli di widget, delle stringhe (per esempio la barra di
ricerca del sito web) e di tutti i testi che non appartengono a un articolo, a una pagina o al menu.

Passa il cursore sopra WPML e clicca su Traduzione stringhe.

Nella pagina che si apre cerca la stringa o il widget che vuoi tradurre. Per aiutarti puoi usare la funzione di ricerca in alto a
destra.

Individuata la stringa clicca sul rispettivo pulsante Traduzioni a destra. Appariranno le stringhe in tutte le lingue create.

Sostituisci il testo che vuoi tradurre, spunta la casella “traduzione completata” e salva.

Adesso puoi vedere che cambiando lingua vengono tradotte anche le stringhe e i titoli di widget che hai aggiornato.
Dunque WPML permette di tradurre i titoli e il testo di widget. Tuttavia possono emergere ulteriori necessità, come
mostrare widget diversi a seconda della lingua. È possibile, ma in questo caso serve un altro plugin: Widget Logic.

Installato Widget Logic vai nella tua bacheca di WordPress. Sotto Aspetto clicca su Widget.

Si apre la pagina con tutti i widget: ciascuno di essi è attivo solo in una lingua, per averli in più lingue è quindi necessario
creare delle copie. Una volta fatto, devi specificare in che lingua attivare i singoli widget.

Come? Clicca sul widget desiderato e aggiorna le impostazioni di lingua nel campo Widget Logic. Qui inserisci il codice:

ICL_LANGUAGE_CODE == ‘LINGUA’

Dove al posto di LINGUA si inserisce il codice della lingua in cui vuoi fare apparire il widget (per esempio
ICL_LANGUAGE_CODE == ‘en’ per l’inglese). In questa area puoi anche modificare il titolo e il testo del widget.

Salva.

Adesso se visiti il sito web e selezioni una lingua diversa, puoi vedere come cambiano anche i widget.

Tradurre  temi  e  plugin  con  WPML  

Creare siti web multilingua su WordPress significa anche dover fare i conti (ovvero tradurre) anche con i testi generati dai
plugin e con i testi statici del tema utilizzato. Il plugin multilingua WPML permette di rimediare anche a questo
problema.

In questo caso serve la versione CMS di WPML, in modo da poter trovare questi testi e sostituirli con la traduzione.

All’interno del file index.php del tema installato inserisci il codice:

<?php _e(‘testo da tradurre’, ‘twentyfourteen’ ); ?>

Adesso dalla Bacheca di WordPress vai in WPML -> Localizzazione del tema e dei plugin. Qui alla voce Stringhe del Tema
clicca sul pulsante Scansiona.

Adesso da WPML vai in Traduzione stringhe e cerca “testo da tradurre”. Clicca su Traduzione e sostituisci i testi tradotti.
Conferma e salva.

Finalmente i testi dei plugin e i testi statici del tema cambiano lingua insieme al resto del sito web.
Parlando di temi per siti web multilingua su WordPress, è molto importante scegliere quello giusto. Ovvero verificare la
compatibilità del tema di WordPress installato con il plugin multilingua WPML.

Ecco alcuni esempi di temi per WordPress compatibili con WPML:

• Enfold  
• Centum  
• Rounder  
• Eunoia  
• Nevada  
• MetroCorp  
• Rework  
• MetroStyle  

Fare  SEO  su  un  sito  multilingua  

Sei riuscito a tradurre tutto il contenuto testuale del tuo sito web multilingua (vetrina o ecommerce), dagli articoli ai testi
statici del tema. Mi spiace rovinare già il momento, ma non abbiamo ancora finito.

Avere uno spazio online in più lingue non significa fare un semplice copia-incolla di testi tradotti. Occorre prendersi cura e
rendere il più efficace possibile ciascuna versione del sito web. Questo include l’ottimizzazione del contenuto tradotto.

Stiamo entrando nel territorio della SEO multilingua, ovvero dell’ottimizzazione del sito web in tutte le lingue che hai
creato.

Il concetto SEO spaventa già di suo, dunque mi rendo conto come il termine SEO multilingua possa suonare un po’ ostico.
Non preoccuparti, in questa guida ti spiego come ottimizzare un sito web multilingua su WordPress in modo semplice.

Consigli  SEO  per  un  sito  web  multilingua  

Partiamo innanzitutto da alcuni consigli utilissimi e facili da applicare. Sette, per l’esattezza.

1. Non  basta  ottimizzare  per  Google  

Per noi motore di ricerca è sinonimo di Google, ma non per il resto del mondo. A seconda della lingua, informati su quale
sia il motore di ricerca più utilizzato nello specifico paese e quali consigli di SEO offre. Per esempio, se includi la lingua
cinese sulla tua piattaforma, ti conviene ottimizzare il sito in cinese per Baidu. Oppure per Yandex in russo e così via.

2. Usa  una  sola  lingua  alla  volta  

Si tratta di una regola d’oro: i motori di ricerca non amano indicizzare un calderone di lingue diverse. Utilizza una sola
lingua alla volta nella ottimizzazione delle parole chiave, nei testi e nei titoli/descrizioni delle immagini. Questo aiuta molto
l’ottimizzazione SEO multilingua.

3. Fai  link  building  nella  stessa  lingua  

Anche per i link vale la stessa regola del punto #2. Se vuoi ottimizzare un sito web multilingua su WordPress, devi inserire
collegamenti esterni con siti nella stessa lingua. Nella versione spagnola del tuo sito web inserirai dunque solo link a siti in
spagnolo.
4. Traduci  i  breadcrumb  e  i  rich  snippet  

Per la SEO multilingua quello che si nasconde dietro a un sito web è importante tanto quanto quello che i visitatori leggono
sulle pagine. Traduci tutti quei contenuti nascosti tanto amati dai motori di ricerca.

5. Collega  le  pagine  corrispondenti  tra  loro  

La gerarchia tra le pagine è un elemento fondamentale ai fini di ottimazione SEO. Tutte le pagine devono essere collegate
fra di loro e facilmente accessibili (con il minor numero di click possibili). Tuttavia, devi tenere presente anche la relazione
tra pagine in lingue diverse. Anziché avere un collegamento comune, collega le pagine corrispondenti nelle varie lingue. Per
capire meglio: collega la pagina Contatti in italiano con la pagina Contatti in inglese.

6. Dosa contenuti internazionali e locali

Come già detto prima, una piattaforma multilingua non vuole dire una copia approssimativa degli stessi testi in più lingue.
La tua attività o brand deve essere presente tanto globalmente quanto localmente. Oltre a tradurre i tuoi contenuti
internazionali, cerca di pubblicare contenuti originali nella lingua locale. Il giusto equilibrio fra i due metodi è la chiave
per il successo.

7. Creare  domini  separati  per  ogni  lingua  

Qui ci addentriamo in un territorio controverso. Ai fini di ottimizzare un sito web multilingua su WordPress è possibile
acquistare domini con estensione diversa (e specifica) per ciascuna lingua. Ad esempio www.miosito.it per l’italiano,
www.miosito.en per l’inglese, www.miosito.de per il tedesco e così via. È un argomento che merita un approfondimento,
per questo ne parliamo nel dettaglio più avanti.

SEO  multilingua  e  WPML  

Chiusa questa utile parentesi, torniamo al nostro plugin multilingua per WordPress preferito. La buona notizia è che WPML
ha pensato proprio a tutto, anche all’ottimizzazione SEO multilingua.

Non solo WPML è compatibile con il plugin WordPress SEO, ma contribuisce direttamente all’ottimizzazione del tuo
sito web multilingua.

Vuoi ottimizzare al massimo i tuoi contenuti lato SEO? Ecco la guida all’eccellente plugin SEO by Yoast.

Leggi  

Vediamo come.

Partiamo dalla homepage. WordPress SEO permette di aggiungere del testo (titolo e descrizione) per facilitare
l’indicizzazione del sito web. Per tradurre il titolo e la meta descrizione della home di un sito web multilingua su
WordPress con WPML, dalla tua Bacheca vai in WPML-> Traduzione stringhe.

Trovi tutti i testi di WordPress SEO sotto la voce ‘admin_texts_plugin_wordpress-seo‘. Individua quello che vuoi tradurre e
clicca su Traduzioni. Sostituisci il testo con la lingua giusta, conferma di aver completato e salva.

Per tradurre il titolo, la meta descrizione e le parole chiave delle altre pagine web del sito, una volta create le copie
della pagine nella altre lingue, basta accedere attraverso WordPress SEO by Yoast e ottimizzarle nella lingua corretta.
Un  dominio  VS  domini  multipli  

Come ho anticipato sopra, utilizzando WPML si può optare per aprire dei domini o sottodomini multipli. Ovvero creare un
sito web diverso per ciascuna lingua. Esistono due modi per farlo.

La prima strada consiste nel creare domini di primo livello nazionali separati su cui caricare i contenuti web in una
singola lingua. Questo significa avere un sito web specifico per ogni lingua, utilizzando l’estensione di riferimento al paese
in cui la lingua è parlata. .it per l’Italia, .de per la Germania, .es per la Spagna, .fr per la Francia.

Altrimenti, puoi optare per creare dei siti web individuali ricorrendo a dei sottodomini del dominio principale che hai
acquistato. In questo caso disporrai un dominio generico di primo livello condiviso dai diversi sottodomini. Così avrai
un’estensione finale comune (per esempio .com) e dei suffissi nazionali. Ecco come: it.miosito.com per l’Italia,
es.miosito.com per la Spagna e così via.

Nel caso di un ecommerce multilingua, oltre all’estensione e alla lingua, andrai a inserire direttamente anche la valuta di
riferimento della nazione.

Anche in questo scenario entra in gioco il plugin multilingua WPML. Infatti questo “gioiellino” è in grado di gestire diverse
lingue su domini o sottodomini differenti. Come? Sono necessarie alcune impostazioni specifiche. E per niente facili.

Insomma, non di certo ciò che consiglierei a principianti e a chi non mastica molto linguaggio informatico.

Tuttavia è possibile. Per farlo (e farlo bene) puoi leggere un utilissimo articolo di aiuto pubblicato dal sito di WPML.

Leggi come impostare il server per lingue diverse su domini differenti.

Ti suggerisco inoltre di contattare il supporto WPML per chiedere assistenza passo per passo con questo complicato
processo. Infine, non fa mai male rivolgersi al proprio hosting provider (il sito su cui hai acquistato i domini con le
diverse estensioni) e chiedere alla sua assistenza clienti come configurare esattamente le impostazioni del tuo server per
creare un sito web multilingua su WordPress con WPML.

Se hai deciso di creare un dominio o sottodominio diverso per ciascuna lingua, puoi tradurre la sitemap. Si tratta di
un’altra tecnica di SEO multilingua volta all’ottimizzazione del tuo sito web

Per tradurre la sitemap, devi installare WordPress SEO by Yoast e abilitare l’opzione ‘Un dominio differente per lingua’
in WPML-> Lingue. In questo modo avrai un file XML per ogni lingua, che puoi trovare in SEO -> XML Sitemap ->
WPML.

Strumenti  di  traduzione  per  un  sito  web  multilingua  

Se vuoi ottenere un sito multilingua autorevole e ben indicizzato, l’aspetto più importante è la qualità delle traduzioni.
Perché il tuo sito web abbia successo tanto in altre lingue quanto in italiano, devi assicurarti che i contenuti siano tradotti
alla perfezione.

Come  scrivere  testi  multilingua  di  qualità  

Diffida dai traduttori automatici. L’errore più grande che tu possa commettere è utilizzare Google Translator e strumenti
similari. Si tratta di software approssimativi e letterali, che non tengono in considerazione le dinamiche di scrittura web.

Non ci credi? Prendi un qualsiasi sito straniero, copia una parte di contenuto e traducilo con Google. Osserva il risultato e
chiediti se ti fideresti di un sito web scritto in questo modo.
I testi tradotti richiedono la medesima cura di quelli originali. Per questo ti consiglio di affidarti a professionisti o
madrelingua.

Tradurre  contenuti  web  con  WPML  

WPML include un altro utile plugin di nome Translation Management. Lo abbiamo già citato ma senza vederne una delle
sue applicazioni principali: determinare “chi traduce cosa”. In altre parole permette di trasformare qualsiasi utente di
WordPress in un traduttore a cui affidare i tuoi testi.

Per farlo devi andare in WPML -> Translation Management-> Traduttori.

Clicca su “locale” e scegli l’utente che vuoi rendere traduttore. Sopra invece scegli la combinazione linguistica (lingua di
origine e lingua di destinazione) da assegnare all’utente.

Per tradurre i contenuti assegnati, l’utente non modificherà l’articolo o le pagine, ma utilizzerà direttamente l’editor di
traduzione di WPML.

Non finisce qui. Può succedere che tu non abbia utenti in grado di tradurre i tuoi testi oppure che non ti fidi completamente
della loro capacità. In tal caso WPML dà la possibilità di trovare dei traduttori professionisti prequalificati. Basta usare
l’opzione ICanLocalize.

Per selezionare e personalizzare i tipi di contenuto da tradurre devi andare in WPML->Translation Management->
Configurazione contenuto multilingue.

Invece, per inviare i contenuti da tradurre vai in WPML->Translation Management-> Bacheca traduzioni.

Qui puoi selezionare quali testi inviare e da chi farli tradurre. Per confermare clicca su Traduci documenti.

A questo punto i tuoi utenti-traduttori riceveranno un’email di notifica e potranno iniziare a lavorare con l’editor di
traduzione di WPML. Se invece hai scelto l’opzione ICanLocalize, WPML invierà il contenuto a dei traduttori
professionisti scelti.

Puoi visualizzare lo stato delle traduzioni sempre nella Bacheca traduzioni di WPML. Vedrai i documenti passare da “non
tradotto” a “traduzione in corso” e infine come già tradotti.

Tradurre  i  contenuti  di  un  sito  web  multilingua:  alternative  

Oltre agli strumenti forniti da WPML, puoi affidare la traduzione dei contenuti a dei traduttori freelance.

Esistono diverse aziende e siti web specializzati nella traduzione in tutte le lingue immaginabili. Uno strumento che io trovo
molto utile per assumere traduttori freelance è Elance. Qui puoi scegliere utenti specializzati nelle diverse lingue, aiutandoti
con la loro reputazione e feedback.

Creare  un  Sito  Web  Vetrina  Multilingua  WordPress  con  WPML:  in  conclusione  

Abbiamo coperto anche l’ultimo aspetto di come creare un sito web multilingua su WordPress con WPML. Adesso non
resta altro che mettersi al lavoro.

WordPress, WPML, Translation Management, WooCommerce e WordPress SEO by Yoast sono tutto ciò di cui hai
bisogno per creare il tuo sito vetrina o il tuo ecommerce multilingua, otre naturalmente a questa guida che spero ti sarà
davvero utile per lo sviluppo della tuo sito web multilingua.
 

 
Cos’è un tema di WordPress
In questa guida esamineremo le procedura necessaria per creare da zero un tema di WordPress, se ne analizzerà la struttura,
si descriveranno le principali funzioni del framework, si cercherà di capire cosa si possa chiedere ad un tema e come
ottenerlo. Il percorso della trattazione seguirà un percorso precisa e condurrà allo sviluppo di un tema completo,
perfettamente funzionante, che sarà scaricabile come allegato dalle pagine della guida e successivamente pubblicato su
Github per eventuali sviluppi futuri.

Le  funzioni  dei  temi  di  WordPress    

Un tema svolge due macro-funzioni: genera il layout e la componente grafica del sito, e aggiunge funzionalità al core di
WordPress. Un tema, quindi, non fornisce solo la veste grafica, ma è anche uno strumento utile a sviluppare la dimensione
"comportamentale" di un sito Web, ciò nello stesso modo dei plugin.

Di regola, un tema dovrebbe essere abbastanza generico da poter essere utilizzato per finalità differenti, ma dovrebbe anche
offrire alcune funzionalità uniche, cosicché l’utente (o acquirente) possa distinguerlo nella miriade di temi disponibili.

Il  file  system  di  WordPress  

Dal punto di vista strutturale, WordPress si presenta con una directory principale, contenente file di valenza globale, come il
file di configurazione wp-config.php e il file .htaccess, e le tre sub-directory wp-admin, wp-content e wp-
includes. Di queste ultime, la prima contiene i file che generano il pannello di amministrazione; la seconda ospita i temi,
i plugin, i file lingua e gli allegati ai contenuti del sito; infine, wp-includes contiene una serie corposa di script che
aggiungono funzionalità all’istallazione, sia dal lato admin che dal lato front-end.

Figura 1. Il contenuto della directory wp-content.

 
I temi sono collocati nella directory /wp-content/themes e, nel caso specifico di WordPress, "installare un tema"
significa semplicemente caricarlo all’interno di questa directory. Una volta istallato, l’anteprima del tema sarà visualizzata
nella pagina denominata "Gestione Temi" del pannello di amministrazione, alla quale si potrà accedere attraverso il
percorso di menu "Aspetto > Temi".

Figura 2. La pagina di Gestione Temi del pannello di amministrazione.

 
Gli unici file indispensabili perché un tema funzioni sono i file style.css e index.php; di questi il primo non è solo
un foglio di stile, ma anche il file in cui vengono memorizzati i metadati necessari al corretto funzionamento del tema
stesso. Quella che segue è una parte dell’intestazione del file style.css del magazine theme denominato Twenty
Fourteen, il tema predefinito di WordPress per il 2014:

/*  
Theme Name: Twenty Fourteen  
Theme URI: http://wordpress.org/themes/twentyfourteen  
Author: the WordPress team  
Author URI: http://wordpress.org/  
...  
*/
Come anticipato, il secondo file indispensabile per un tema è index.php, questo fornisce il template della pagina iniziale
del sito e viene normalmente strutturato in quattro diverse sezioni:

1. intestazione;  
2. contenuti;  
3. sidebar;  
4. fondo  pagina.  

È prassi incorporare il codice che compone le diverse sezioni in file esterni, si avranno così i file header.php,
sidebar.php e footer.php. Anche i contenuti della pagina possono essere generati sia all’interno del file
index.php, che in template esterni, dipendenti dal formato dell’articolo.

Figura 3. La struttura del tema Twenty Fourteen.


 
Il file index.php viene caricato ogni qual volta non esista un template più specifico per il tipo di pagina richiesta,
secondo una gerarchia prestabilita, definita Template Hierarchy. In base a questa gerarchia, dei template, quando l’utente
accede alla Home Page, WordPress cercherà prima il file home.php; ma se questo non esiste, sarà caricato il file
index.php. Così, in base alla pagina, un tema potrà essere dotato di un file single.php, per i singoli articoli,
archive.php, per le pagine di archivio, page.php, per le pagine statiche, e così via. Mancando questi, sarà sempre
caricato index.php.

WordPress permette anche di creare template pagina, ossia particolari template destinati alle pagine statiche. Sempre
all’interno della directory del tema, potranno essere collocati una cartella destinata ai file di lingua, nonché tutti gli script e i
fogli di stile necessari allo sviluppo del sito.

La  distribuzione  dei  temi  per  WorPress    

È buona norma progettare un tema avendo come obiettivo la sua distribuzione. Un tema può essere distribuito
gratuitamente, al fine di accrescere la reputazione dello sviluppatore o per promuovere una versione a pagamento; oppure
può essere distribuito commercialmente e diventare fonte diretta di guadagno. In entrambi i casi, bisogna tener presente che
WordPress è rilasciato sotto licenza GPL, la quale prevede che ogni opera derivata venga rilasciata sotto le stesse
condizioni.

I temi (e i plugin), quindi, utilizzando le funzioni PHP del framework, vanno considerati come opere derivate, da distribuire
secondo la stessa licenza GPL. Se ciò è vero per il codice PHP, non può dirsi altrettanto per il codice CSS e per i file
immagine, che non dipendono da WordPress. Questi ultimi tipi di file devono quindi essere considerati opere separate e non
derivate.

In conclusione, la licenza GPL non si applica al tema nel suo complesso, ma solo ai file PHP.

Terminata la fase relativa alla presentazione dei temi di WordPress, dedicheremo le prossime pagine della guida ad
esaminare le diverse componenti che costituiscono un tema.

I template generali in WordPress


Il Codex definisce i template come quei file che controllano il modo in cui vengono rese a video le pagine di WordPress.
Ogni pagina viene normalmente strutturata in sezioni, ognuna delle quali è generata da un determinato template, incorporato
nella pagina principale grazie a specifiche funzioni del framework, definite template tag.

La  struttura  di  una  pagina  

In WordPress una pagina si struttura in quattro blocchi: intestazione (header), corpo della pagina (content), una o più aree
dedicate ai widget (sidebar), fondo pagina (footer). Nel caso delle pagine dedicate a singoli articoli, va prevista un’area
aggiuntiva destinata ai commenti.

In PHP, la funzione include() incorpora all’interno di uno script il contenuto di un file esterno; quando si sviluppa un
tema di WordPress, però, al posto di include() è opportuno utilizzare funzioni specifiche del framework che permettono
di inserire con maggior sicurezza e semplicità i template che costituiscono le parti della pagina. L’immagine che segue
mostra il file index.php del Blank Theme di HTML5 Reset, cui si farà spesso riferimento in questa guida:

Figura 1. La pagina index.php del Blank Theme.


 
Le funzioni get_header(), get_sidebar() e get_footer() sono Template Tags e hanno lo scopo specifico di
includere dinamicamente i template generali header.php, sidebar.php e footer.php. I contenuti della pagina,
invece, vengono generati da un ciclo iterativo definito Loop che si presenta in questo modo:

<?php if  (have_posts()) : while  (have_posts()) : the_post(); ?>  


...  
<?php endwhile; ?>

All’interno del Loop vengono invocati altri template tags, tramite i quali si accede al database e si manda l’output a video.

Figura 2. Relazione tra template principali, template tags e template parts.


 
Header  

Il template tag get_header() include il template header.php. Se esiste un template più specifico per il tipo di pagina,
questo andrà nominato header-{name}.php, e alla funzione andrà passata la stringa name come argomento:
get_header( 'name' ). La home page del sito, ad esempio, potrebbe avere un’intestazione specifica nel template
header-home.php, che andrebbe inclusa con get_header( 'home' ).

Il file header.php contiene l’intestazione del documento HTML, con i vari tag meta, link e script. È il file che
genera la parte superiore della pagina con il menu di navigazione. Quello che segue è il codice di un header.php
notevolmente semplificato:

Figura 3. Estratto del file header.php del Blank Theme.


 
Come gli altri template generali, il file header.php utilizza i tag del core per recuperare informazioni dal database e con
queste generare la struttura HTML della pagina. Oltre ai template tag, nell’header della pagina andrebbe sempre invocata la
funzione wp_head(), da inserire prima della chiusura del tag head (ci si riferisca al Codex per i dettagli).
Sidebar  

La sidebar è un contenitore di blocchi di codice HTML – definiti widget – che contengono informazioni correlate ai
contenuti del sito Web. In una pagina possono essere inserite diverse sidebar, ognuna collocata in un’area diversa. La
sidebar viene generata dal file sidebar.php, o da più specifici file sidebar-{name}.php, e incorporata nei template
del sito grazie al template tag get_sidebar() (maggiori info nel Codex). Nel caso di template specifici, alla funzione
andrà passata la stringa 'name'. Ecco un generico sidebar.php:

Figura 4. Il file sidebar.php del Blank Theme.

 
Footer  

Il footer è la parte inferiore della pagina del sito. Questa spesso contiene informazioni aggiuntive, note di copyright, form di
ricerca. Vista l’eterogeneità delle informazioni, spesso nel footer trova posto un’ulteriore sidebar, sempre incorporata dal
template tag get_sidebar().

Figura 5. Estratto del file footer.php del Blank Theme.


 
Il footer deve sempre contenere un richiamo alla funzione wp_footer(), da collocare subito prima della chiusura del
body, come illustrato nel Codex.

Figura 6. Struttura generale di una pagina di WordPress.


 
Riferimenti  del  Codex  

Il Codex è il riferimento ufficiale e imprescindibile per chiunque voglia sviluppare su WordPress, e al Codex si farà
frequente rinvio in questa guida. Qui si troverà l’elenco completo dei template tags e l’indice delle risorse relative ai
template. Altra risorsa indispensabile è l’articolo Stepping into templates.

I template files di WordPress


Quando l’utente clicca su una voce di menu, il client invia al server una query string in base alla quale WordPress seleziona
i contenuti dal database e sceglie il template da utilizzare per generare la pagina, seguendo la rigorosa logica della
Template Hierarchy.

Il  Loop:  introduzione  

Sebbene non esistano regole generali sulla struttura che deve avere un template file, generalmente questo non manca dei tag
get_header(), get_sidebar() e get_footer(), che includono le parti della pagina e del ciclo iterativo (Loop)
che accede al database e lancia a video i contenuti:

<?php if  (have_posts()) : while  (have_posts()) : the_post(); ?>  


...  
<?php endwhile; ?>  
...  
<?php endif; ?>

Il Loop genera quindi un elenco di articoli, il cui markup dipende dalle decisioni di chi sviluppa il tema. Per ogni articolo
potrà essere visualizzato un estratto del contenuto principale o un testo alternativo (excerpt); potrà essere visualizzata o
meno un’immagine di anteprima (post thumbnail); potranno essere visualizzate le categorie, i tag, la data di pubblicazione,
l’autore e tutti i possibili metadati. Tutte queste opzioni devono essere attentamente vagliate quando si progetta un tema.

Figura 1. Il Loop del file archive.php del Blank Theme di HTML5 Reset

 
Quelli che seguono sono i principali template da tenere in considerazione quando si progetta un tema.

Il  file  index.php  

index.php costituisce il template principale di un tema, sebbene sia allo stesso tempo quel template cui WordPress
ricorre solo come soluzione di fallback, ossia quando mancano template specifici per il tipo di richiesta del client.

Figura 2. Il file index.php del Blank Theme

 
Proprio per questa sua caratteristica, il file index.php deve essere adatto a generare ogni tipo di pagina, dagli archivi di
notizie, agli articoli singoli fino alle pagine statiche.

Gli  archivi  di  notizie  

Per WordPress un archivio è un elenco di post. L’utente può chiedere i post pubblicati in un dato periodo, creati da un
determinato autore, appartenenti ad una certa categoria, o etichettati con uno specifico tag. In tutti questi casi viene richiesta
una pagina d’archivio. Qualora non esista un template più specifico per il tipo di pagina richiesta, WordPress cercherà il
generico file di archivio archive.php (in mancanza del quale tornerà al file index.php).
Normalmente il template archive.php è simile al file index.php, avendo anch’esso lo scopo di fornire un elenco di
articoli.

Figura 3. Il file archive.php del Blank Theme

 
I  template  specifici:  categorie,  tag,  autori  

Esistono numerosi tipi di archivi, e WordPress permette di creare una pagina specifica per ognuna delle varie tipologie. Si
avranno, quindi, i seguenti template:

• author.php  
• category.php  
• date.php  
• tag.php  
• taxonomy.php  

La specificità può essere ancora maggiore: è possibile creare, infatti, template diversi per ogni
categoria/autore/tag/tassonomia, aggiungendo un suffisso al nome del file. Così, ad esempio, per le categorie si avranno i
seguenti template:

• category.php  
• category-$id.php  
• category-$slug.php  
Allo stesso modo, per i tag si avrà:

• tag.php  
• tag-$id.php  
• tag-$slug.php  

L’elenco dei template è lungo, e si rinvia ancora al Codex per ogni utile approfondimento.

Post  singoli  e  pagine  statiche  

Oltre che per gli archivi, è possibile creare template adatti alla visualizzazione di singoli contenuti, che possono essere
articoli del blog, pagine statiche, attachment, e post personalizzati.

In questo caso la struttura del template sarà sensibilmente diversa dai file di archivio, sebbene in entrambi i casi saranno
presenti i tag get_header(), get_sidebar() e get_footer(), oltre che, ovviamente, il Loop, che in questo caso
manderà a video un solo elemento.

Figura 4. Il codice del file single.php del Blank Theme

 
Per i singoli contenuti, WordPress dispone dei seguenti template:

• attachment.php  
• page.php  
• single.php  
• custom.php  

Anche questa volta è possibile creare template più specifici. Nel caso dei post, avremo:

• single.php  
• single-$post.php  
• single-$posttype.php  

Come prima, si rinvia al Codex per la descrizione analitica dei template.

Altri  template  

WordPress dispone di altri template, che vanno a completare il mosaico permettendo un controllo assoluto dell’aspetto del
sito.

• I  template  front-page.php  e  home.php  sono  utilizzati  per  la  visualizzazione  della  pagina  
iniziale:  il  primo  nel  caso  di  una  pagina  statica,  il  secondo  nel  caso  in  cui  si  voglia  un  
template  più  specifico  del  file  index.php;  
• Il  template  404.php  è  destinato  alle  pagine  di  errore;  
• search.php  mostra  i  risultati  di  una  ricerca  interna  al  sito;  
• comments-popup.php  genera  una  finestra  di  popup  per  i  commenti.  

Conclusioni  e  riferimenti  

In questo capitolo si è voluta offrire una panoramica dei template file di WordPress e si è fatto riferimento ai seguenti
articoli del Codex:

• Stepping  into  Templates  


• Templates  
• Template  Hierarchy  
• Theme  Development  

Nel prossimo capitolo si presenteranno le funzioni del framework che permettono di creare la struttura HTML dei template
file.

I file style.css e functions.php nei temi di


WordPress
Un tema dispone sempre di un file style.css, richiesto obbligatoriamente da WordPress, e di un file functions.php,
che, sebbene non strettamente necessario per i temi, è fondamentale qualora si debbano aggiungere funzionalità al core del
CMS.

Il  file  style.css  

È molto di più di un foglio di stile. Il file, infatti, fornisce a WordPress tutte le informazioni necessarie a gestire il tema:
nome, autore, descrizione, licenza, e molto altro. L’immagine seguente mostra l’intestazione del file style.css del tema
Twenty Fourteen:
Figura 1. Intestazione del file style.css di Twenty Fourteen

 
I metadati che compongono l’intestazione del file style.css devono essere forniti all’interno di un commento.
Particolare attenzione va posta al nome del tema, che deve sempre essere univoco. Nel caso dovessero essere istallati due
temi con lo stesso nome, infatti, WordPress non potrebbe gestirli correttamente.

Quello che segue è l’elenco degli Header-Names che possono essere utilizzati nel foglio di stile:

• Author  
• Author URI  
• Description  
• Domain Path  
• Status  
• Tags  
• Template  
• Text Domain  
• Theme Name  
• Theme URI  
• Version  

Le intestazioni possono essere estese con l’aggiunta di altri nomi alla lista appena vista, come ad esempio Licence e
License URI (a tal proposito si veda come esempio il tema Twenty Fourteen). Non tutti gli Header-Names sono
indispensabili; per la corretta gestione del tema, però, è necessario prevedere almeno i nomi che consentano di individuarlo
e descriverlo.

È importante ricordare che ogni coppia nome/valore va collocata su un rigo singolo e viene separata dal simbolo dei due
punti (":"), maggiori informazioni sulle regole da seguire per l’intestazione del foglio di stile sono disponibili nel Codex.
Nel caso si stia sviluppando un Child Theme, cioè un tema derivato da un tema principale (Parent Theme), il foglio di
stile deve contenere anche un riferimento al tema principale, individuato dal nome Template. Nell’immagine che segue,
si riporta, a titolo di esempio, l’intestazione del foglio di stile di un Child Theme basato su Twenty Fourteen.
Figura 2. Intestazione dello style.css di un Child Theme basato su Twenty Fourteen

 
Il  file  functions.php  

Sebbene, come anticipato, non sia strettamente necessario, il file functions.php è presente nella quasi totalità dei temi.
Questo permette di estendere il core di WordPress con quelle funzionalità che spesso vengono aggiunte tramite plugin. Ciò
avviene sia attraverso la definizione di nuove funzioni, sia utilizzando le funzioni del framework. Il file consente, inoltre, di
attivare tutte quelle funzionalità che sono specifiche dei temi, come i post thumbnail, i menu personalizzati, le aree destinate
ai widget. La figura proposta di seguito mostra un estratto del codice del file functions.php del tema twenty Fourteen:

Figura 3. Codice del file functions.php del tema Twenty Fourteen


 
Una differenza da sottolineare tra il file functions.php di un tema e lo script principale di un plugin è che le
funzionalità aggiunte dal primo si applicano solo se il tema è attivo; al contrario, le funzionalità di un plugin vengono
aggiunte al core indipendentemente dal tema attivo. Il functions.php è inoltre il file in cui richiamare quelle funzioni
dell’API (Application Programming Interface), comunemente definite filtri e azioni, che estendono le funzionalità di
WordPress fino al punto di trasformare un normale sito Web in una vera e propria Web application.

La funzione del file rimane la stessa, sia che si sviluppi un tema, sia che si lavori su un Child Theme. In quest’ultimo caso è
opportuno precisare che il functions.php è l’unico file del tema derivato che non sovrascrive il corrispondente file del
tema originale, ma viene caricato in aggiunta al suo corrispondente. Più precisamente, il functions.php del Child
Theme viene caricato prima del file presente nella directory del parent.

Riferimenti  online  

Abbiamo fatto riferimento alle seguenti risorse:

Sul file style.css


• File  Header  
• Theme  Development  
• Child  Themes  
• CSS  

Sul file functions.php

• Functions  File  Explained  


• Child  Themes  

In seguito inizieremo ad analizzare le funzioni del framework.

I template tag nei temi di WordPress


I template tag sono funzioni definite nel core di WordPress che prelevano informazioni dal database e generano
dinamicamente un output, quest’ultimo può essere mandato direttamente a video o restituito come valore di una variabile.

Molti template tag generano informazioni relative a post e pagine, come il titolo, l’autore, la data di pubblicazione, etc.
Questi tag vanno utilizzati all’interno del Loop. Altri tag generano informazioni di carattere generale e possono essere
utilizzati al di fuori del Loop.

Tag  frequentemente  utilizzati  

Tra i tag di utilizzo più frequente, bloginfo() fornisce un semplice esempio di come restituire a video informazioni sul
sito Web corrente:

<h2 class="site-description"><?php bloginfo( 'description'  ); ?></h2>

L’argomento individua il tipo di informazione richiesta e la funzione invia direttamente l’output al browser. Il codice
precedentemente proposto manda a video il seguente testo:

<h2 class="site-description">Un nuovo sito targato WordPress</h2>

Spesso l’output restituito a video non è costituito da una semplice stringa di testo, ma da un frammento di codice HTML:

<article id="post-<?php the_ID(); ?>"  <?php post_class(); ?>>

the_ID() restituisce l’ID del post corrente in forma di stringa; post_class(), invece, restituisce un frammento di
codice HTML, sicché l’output a video sarà:

<article id="post-90"  class="post-90 post type-post status-publish format-standard


hentry category-news">

Tra le molte decine di tag, è possibile individuare due sottogruppi che si presentano con caratteristiche omogenee: i tag con
prefisso the_ e i tag con prefisso get_.
I  tag  the_  

Il prefisso the_ individua un tag che manda a video un output. the_title() e the_permalink(), ad esempio,
restituisce a video il titolo e il permalink di un post (o di una pagina) e deve necessariamente essere utilizzato all’interno del
Loop. Si consideri questo esempio:

<h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>

Con questa istruzione vengono stampati a video il permalink e il titolo di un post all’interno di un titolo delimitato da h2.
Altri tag the_ di impiego comune sono:

Tag Descrizione
the_author() Produce  una  stringa  con  il  nome  dell’autore  di  un  post.
the_author_meta() Mostra  ogni  altro  tipo  di  informazione  sull’autore  del  post.
the_time()  e  the_date() Mostrano  ora  e  data  di  pubblicazione.
the_excerpt()  e  the_content() Mandano  a  video  il  riassunto  e  il  contenuto  principale  del  post.
the_category()  e  the_tags() Generano  l’elenco  delle  categorie  e  dei  tag  post.

I  tag  get_  

Se i tag the_ stampano un output a video, i tag get_ restituiscono una stringa da gestire via PHP. Il framework dispone,
per molti tag the_, di un corrispondente tag get_. Così i tag get_permalink() e get_the_title() permettono
di ottenere lo stesso risultato dell’esempio precedente:

<a href="<?php esc_url( get_permalink() ); ?>"><?php echo  get_the_title();


?></a></h2>

get_permalink() e get_the_title() possono essere utilizzati al di fuori del Loop, e quindi si prestano ad una
molteplicità di impieghi. Altri tag di uso comune sono get_bloginfo(), get_the_author(),
get_the_author_meta(), get_the_time(), get_the_date(), get_the_excerpt() e
get_the_content() i cui nomi rendono facilmente intuibile la funzione svolta.

Tag  condizionali  

Sono funzioni che permettono di testare una condizione. Grazie a questi tag, è possibile generare un output alternativo a
seconda del valore TRUE o FALSE restituito. is_single(), ad esempio, restituisce TRUE al caricamento di una pagina
singola:

if  ( is_single() ) :  
the_title( '<h1 class="entry-title">', '</h1>'  );  
else  :  
the_title( '<h1 class="entry-title"><a href="'  . esc_url( get_permalink() ) .
'" rel="bookmark">', '</a></h1>'  );  
endif;

Altri tag condizionali di uso corrente sono is_home() e is_front_page(), che testano se la pagina corrente sia la
Home Page del sito Web corrente (blog o pagina statica); is_page(), che verifica che l’utente si trovi in una pagina
statica; is_category(), che verifica la categoria del post corrente.
Include  tags  
Gli  Include  Tags,  di  cui  si  è  già  parlato  nei  capitoli  precedenti,  sono  funzioni  che  includono  il  
contenuto  di  specifici  template.  Si  tratta  dei  seguenti  template  tags:    

• get_header()  
• get_footer()  
• get_sidebar()  
• get_template_part()  
• get_search_form()  
• comments_template()  

Anche in questo caso i nomi dei tags rendono facilmente intuibile la funzione svolta

I  parametri  

Come tutte le funzioni PHP, i template tag possono accettare o meno argomenti. bloginfo(), ad esempio, accetta una
stringa che individua il tipo di dato da mandare a video. Nel caso non venisse passato alcun argomento, bloginfo()
stamperà il nome del sito Web corrente. Alcuni tag accettano argomenti come ogni funzione PHP; a tal proposito si
consideri la seguente istruzione:

<?php single_post_title( 'Title: ', TRUE ); ?>

Qui il primo argomento è un testo da visualizzare prima dell’output, il secondo stabilisce se la funzione deve mandare a
video il testo, o restituirlo in una variabile PHP. Infine, alcuni tag accettano argomenti nella forma di array o di querystring:

<?php wp_list_categories( 'orderby=name&exclude=4,5&title_li=<h2>'  . __('Events') .


'</h2>&taxonomy=event'  ); ?>

L’argomento passato alla funzione consiste in una querystring che imposta i valori di quattro parametri: orderby,
exclude, title_li e taxonomy. In alternativa alla querystring, gli stessi parametri avrebbero potuto essere trasmessi
come elementi di un array.

Riferimenti  online  

In questo capitolo si è fatto ampio riferimento al Codex di WordPress, e in particolare ai seguenti articoli:

• Template  Tags  
• Stepping  into  Template  Tags  
• Anatomy  of  a  Template  Tag  
• How  to  pass  tag  parameters  
• Conditional  Tags  
• Include  Tags  

Nel prossimo capitolo si parlerà nel dettaglio della gerarchia dei template.

La gerarchia dei template in WordPress


Nei primi capitoli di questa guida si è più volte fatto riferimento alla gerarchia dei template. Si tratta della gerarchia in base
alla quale WordPress individua il template con cui viene generata ogni singola pagina del sito. L’informazione relativa al
tipo di pagina viene trasmessa tramite le querystring e la selezione del template avviene in base ai nomi dei file disponibili.

Tra tutti i template file, l’unico indispensabile è il file index.php, utilizzato da WordPress qualora manchino template più
specifici per la pagina richiesta dall’utente.

La  pagina  iniziale  

Per restituire la pagina iniziale di un sito Web basato su WordPress sono previsti due template: home.php e front-
page.php. Il primo viene utilizzato quando la pagina iniziale mostra gli ultimi articoli del blog; il secondo quando viene
impostata una pagina statica nel menu “Impostazioni lettura” del pannello di amministrazione.

In mancanza del file home.php, viene caricato il file index.php, in mancanza del file front-page.php, invece,
WordPress cercherà il template page.php, nel caso in cui la pagina iniziale sia una pagina statica; in alternativa, qualora
la pagina iniziale sia un elenco di articoli, WordPress cercherà di nuovo il template home.php.

Figura 1. Gerarchia di file della Front page

 
Pagine  singole  

Per rendere singoli post e pagine statiche sono disponibili due template generali: single.php per gli articoli e
page.php per le pagine statiche. Prima di questi due template, però, WordPress ne cercherà di più specifici. Quella che
segue è la gerarchia prevista per articoli, tipi di post personalizzati e allegati:

Nel caso dei Post avremo:

• single-post.php  
• single.php  

Nel caso dei Custom post types avremo invece:

• single-$posttype.php  
• single.php  

Infine, nel caso degli allegati:

• $mimetype.php  
• $subtype.php  
• $mimetype_$subtype.php  
• attachment.php  
• single.php  

Le pagine statiche possono avere un template specifico per la singola pagina:

• $custom.php  
• page.php  

Oppure  seguire  lo  schema  della  gerarchia:    

• page-$slug.php  
• page-$id.php  
• page.php  

Come sempre, ogni qual volta manchino tutti i template della gerarchia, WordPress cercherà il file index.php.

Figura 2. Gerarchia per le pagine singole

 
Pagine  di  archivio  

Una pagina di archivio è una pagina che ospita un elenco di notizie. Può trattarsi delle notizie di una specifica categoria,
etichettate con un certo tag o con una determinata tassonomia, appartenenti ad un tipo di post personalizzato, create da un
certo autore, o, infine, pubblicate in una certa data.

In tutti questi casi, WordPress cercherà template specifici per il tipo di archivio, secondo il seguente schema:

Archivio File  di  template


category-$slug.php  
category-$id.php  
Categorie category.php  
archive.php
author-$nicename.php  
author-$id.php  
Autore author.php  
archive.php
Post  type   archive-$posttype.php  
(Tipo  di  post) archive.php
taxonomy-$taxonomy-$term.php  
taxonomy-$taxonomy.php  
Tassonomia taxonomy.php  
archive.php
tag-$slug.php  
tag-$id.php  
Tag tag.php  
archive.php
date.php  
Data archive.php

Figura 3. Gerarchia degli archivi

 
Commenti,  404  e  risultati  di  ricerca  

Gli ultimi template generano il pop-up dei commenti (comments-popup.php), la pagina di errore 404 (404.php) e la
pagina che mostra i risultati di una ricerca interna al sito (search.php).

Figura 4. Gerarchia per pagine specifiche


 
Nell’immagine conclusiva di questo capitolo viene mostrata un’infografica dell’intera struttura gerarchica dei template.

Figura 5. Struttura gerarchica dei template


 
Riferimenti  online  

Per ogni approfondimento degli argomenti trattati in questo capitolo, si rinvia alle seguenti risorse:

• Template  Hierarchy  
• WordPress  Template  Hierarchy  

Il file style.css: intestazione e layout della pagina


Il file style.css non è solo il foglio di stile principale del tema, è anche il file che fornisce a WordPress tutte le
informazioni necessarie al corretto funzionamento del tema stesso. Queste informazioni sono contenute in un’intestazione
sotto forma di commento e sono strutturate come coppie chiave/valore, definite seguendo le regole indicate nella File
Header Specification.

La seconda parte del file contiene le dichiarazioni CSS che permettono di creare la veste grafica del sito. WordPress genera
numerosissimi nomi di classi CSS che vengono assegnati automaticamente agli elementi che compongono le pagine del
front-end. Una volta noti i nomi delle classi, sarà agevole definire con precisione le caratteristiche grafiche di ogni elemento
della pagina.

L’intestazione  del  file  

Quelli che seguono sono i metadati che possono comporre l’intestazione del file style.css:

Chiave Descrizione
Name il  nome  del  tema  
ThemeURI la  URI  della  home  page  del  tema  
Description la  descrizione  del  tema  
Author l’autore  del  tema  
AuthorURI il  sito  web  dell’autore  
Version la  versione  corrente  
Template previsto  solo  per  i  child  themes,  indica  la  directory  del  parent  theme  (obbligatorio)  
Status indica  se  il  tema  è  pubblicato  
Tags etichette  utilizzate  per  descrivere  il  tema  
TextDomain il  text  domain  utilizzato  per  la  localizzazione  
DomainPath il  percorso  ai  file  contenenti  le  traduzioni  

La lista proposta non è tassativa e altre coppie chiave/valore possono essere aggiunte all’elenco. Quello che segue è invece
un esempio di intestazione:

/*  
Theme Name: Seventy One Theme  
Theme URI: http://example.com  
Description: A basic theme for HTML.it readers  
Author: Carlo Daniele  
Author URI: https://www.linkedin.com/in/carlodaniele  
Version: 0.1  
*/

Queste stesse informazioni saranno visibili nel pannello di amministrazione, nella scheda "Dettagli Tema" della pagina
"Aspetto > Temi".

Figura 1. Dettagli del tema


 
Si passa poi alla dichiarazione degli stili. Non è strettamente necessario, ma, prima di creare i propri stili, è una buona
abitudine azzerare gli stili predefiniti dei browser. A tal scopo, in questa guida si è fatto ricorso al Reset CSS di Eric Meyer.

Il  layout  delle  pagine  

Dopo aver azzerato gli stili predefiniti, si passa alla progettazione della presentazione del sito, con la creazione del layout.
Si vedrà più avanti come generare il markup, ma già da ora si può definire il seguente schema:

<div  id="page"  class="site">  


   
<header  id="site-header"  class="site-header"  role="banner">  
<h1  class="site-title"> ... </h1>  
<nav  id="primary-navigation"  class="site-navigation primary-navigation"  
role="navigation">  
<div  class="menu-main-menu-container">  
<ul  id="menu-main-menu"  class="nav-menu"> ... </ul>  
</div>  
</nav>  
</header>  
   
<div  id="main-content"  class="main-content">  
<div  id="content"  class="content-area"  role="main"> ... </div>  
</div>  
   
<aside  id="sidebar">  
<div  id="primary-sidebar"  class="primary-sidebar widget-area"  
role="complementary"> ... </div>  
</aside>  
   
<footer  id="site-footer"  class="site-footer"  role="contentinfo"> ... </footer>  
   
</div>

La div#page esterna costituisce il contenitore generale. I blocchi interni sono costituiti dall’elemento header,
contenente il titolo del sito e il menu principale di navigazione, dalla div#main-content, che ospita i contenuti,
dall’elemento aside, che ospita la sidebar principale e, infine, dall’elemento footer, che ospiterà una diversa sidebar e
le informazioni di copyright.

Figura 2. Struttura del layout

 
Definita la struttura, si può procedere alla creazione del layout. Nel foglio di stile andranno aggiunte le seguenti istruzioni:

#page {  
margin: 0  auto;  
width: 90%;  
max-width: 960px;  
}  
   
#site-header {  
margin: 0  1.0416667%;  
padding-top: 2.7659574%;  
width: 97.9166667%;  
}  
   
#primary-navigation {  
margin-top: 2.7659574%;  
margin-bottom: 2.7659574%;  
width: 100%;  
}  
   
#main-content {  
margin-right: 1.0416667%;  
float: right;  
width: 72.7083333%;  
}  
   
#sidebar {  
border-right: 2px  solid  #e8e8e8;  
margin-right: 1.0416667%;  
margin-left: 1.0416667%;  
padding-right: 1.0416667%;  
float: left;  
width: 22.7083333%;  
}  
   
#site-footer {  
float: left;  
margin: 2.7659574%  1.0416667%  1.0416667%  0;  
clear: both;  
width: 97.9166667%;  
}

Come è possibile notare, sono state utilizzate unità di misura relative per fare in modo che il layout sia flessibile e si adatti
alla dimensione dello schermo. Il blocco #main-content occupa il 72% circa dell’area disponibile, mentre la barra
laterale occupa il 22%. Le proporzioni vanno ora adattate agli schermi di dimensioni inferiori:

@media screen  and (max-width: 800px) {  


#main-content {  
float: left;  
width: 97.9166667%;  
}  
   
#sidebar {  
float: left;  
width: 97.9166667%;  
}  
}
Definito il layout generale, si passa alla progettazione grafica degli elementi della pagina. Nei prossimi capitoli si vedrà,
quindi, come definire l’aspetto dei singoli elementi delle pagine, sfruttando principalmente le classi generate da WordPress.

Riferimenti  e  conclusioni  

Come in precedenza, anche in questo capitolo si è ampiamente fatto riferimento al Codex di WordPress, in particolare sono
state seguite le linee guida delle seguenti risorse:

• File  Header  
• L’oggetto  WP_Theme  
• CSS  Coding  Standard  

Il file style.css: body, header e menu di


navigazione
WordPress genera un consistente numero di classi e ID che assegna automaticamente agli elementi della pagina. Ciò
consente di modificare facilmente la presentazione delle pagine e di rifinire dettagliatamente l’aspetto di ogni singolo
elemento. Una volta noto lo schema delle classi, sarà anche agevole produrre più versioni dello stesso tema.

Da qui in avanti si vedrà, quindi, come definire l’aspetto dei singoli elementi.

Il  body  del  documento  

WordPress assegna all’elemento body un numero variabile di classi a seconda della pagina richiesta dall’utente. Nessuna di
queste è strettamente necessaria, ma ognuna consente di personalizzare la pagina a seconda che essa contenga un post, un
archivio, o una pagina di errore. Le classi vengono assegnate grazie al tag body_class():

<body <?php body_class(); ?>>

In un archivio-categoria, questa istruzione genera un codice simile a quello che segue:

<body  class="archive category category-cms category-2 logged-in admin-bar ... ">

Si avranno, quindi, a disposizione nomi di classe specifici per il tipo di pagina:

.home {}  
.blog {}  
.page {}  
.archive {}  
.search {}  
.error404 {}

Nomi di classe che individuano il tipo di archivio:

.category {}  
.tag {}  
.tax-{taxonomy} {}  
.term-{term} {}  
.post-type-archive {}  
.author {}  
.date  {}

E nomi di classe assegnati a pagine singole:

.single {}  
.single-post {}  
.single-author {}

Nel file qui allegato è disponibile l’elenco completo delle classi generate dal tag body_class().

La  testata  della  pagina  

La testata della pagina viene racchiusa in un elemento header, generalmente inserito nel file header.php. Nel tema che
ci si propone di sviluppare, l’header è strutturato come segue:

<header  id="site-header"  class="site-header"  role="banner">  


<a  class="home-link"  href="#"  title="#"  rel="home">  
<h1  class="site-title">Title</h1>  
<h3  class="site-description">Description</h3>  
</a>  
<nav  id="primary-navigation"  class="site-navigation primary-navigation"  
role="navigation">  
...  
</nav>  
</header>

L’header contiene il titolo, la descrizione del sito e il menu di navigazione, racchiuso in un elemento nav. Di seguito gli
stili degli elementi:

.site-header {}  
.site-header a {  
color: #555;  
text-decoration: none;  
}  
.site-header a:hover {  
color: #222;  
}  
.site-title {  
margin-top: 0;  
margin-bottom: 0;  
}  
.site-description {  
font-size: 1.2em;  
}

Il  menu  di  navigazione  

All’interno dell’header, particolare importanza riveste il menu di navigazione. Questo viene generato dal seguente
template tag:

<?php wp_nav_menu( array( 'theme_location'  => 'primary', 'menu_class'  => 'nav-menu'  


) ); ?>

Essp dispone di diverse decine di classi che vengono assegnate agli elementi del menu di navigazione a seconda del
contesto. Il menu a cui si farà riferimento presenta la seguente struttura:
<nav  id="primary-navigation"  class="site-navigation primary-navigation"  
role="navigation">  
<div  class="menu-main-menu-container">  
<ul  id="menu-main-menu"  class="nav-menu">  
<li  id="menu-item-79"  class="menu-item menu-item-type-custom menu-item-
object-custom current-menu-ancestor menu-item-has-children menu-item-79">  
<a  href=" ... ">CMS</a>  
<ul  class="sub-menu"> ... </ul>  
</li>

Per il tema che si sta sviluppando, si è pensato di utilizzare un menu Suckerfish nella sua versione originale, in puro CSS:

/* custom class added to nav element from header.php */  


.primary-navigation {  
float: left;  
width: 100%;  
border-top: 1px  solid  rgba(57, 114, 73, 0.6);  
border-bottom: 1px  solid  rgba(57, 114, 73, 0.6);  
background-color: rgba(199, 225, 186, 0.6);  
}  
.primary-navigation ul {  
margin: 0;  
background-color: rgba(57, 114, 73, 0.9);  
}  
.primary-navigation li {  
min-width: 8em;  
position: relative;  
float: left;  
line-height: 2.4em;  
white-space: nowrap;  
padding-right: .4em;  
}  
.primary-navigation a{  
display: block;  
text-align: left;  
padding-left: .4em;  
}  
.primary-navigation ul ul {  
display: none;  
}  
.primary-navigation li li {  
float: none;  
}  
.primary-navigation ul ul ul{  
display: none;  
top: 0;  
left: 100%;  
}  
.primary-navigation li ul {  
display: none;  
position: absolute;  
/* old explorer versions */  
top: 1em;  
left: 100%;  
}  
/* all other browsers */  
.primary-navigation li>ul{  
top: auto;  
left: auto;  
}  
.primary-navigation li:hover>ul, nav li.hover>ul{  
display: block;  
}  
.primary-navigation ul li{  
text-align: left;  
}  
.primary-navigation ul li a {  
display: block;  
width: 100%;  
text-transform: uppercase;  
line-height: 2.4em;  
text-decoration: none;  
}  
.primary-navigation ul li a {  
color: #397249;  
}  
.primary-navigation ul ul li a {  
color: #c7e1ba;  
}  
.primary-navigation a:hover {  
color: #000;  
background-color: #c7e1ba;  
}  
.primary-navigation .current_page_item > a,  
.primary-navigation .current_page_ancestor > a,  
.primary-navigation .current-menu-item > a,  
.primary-navigation .current-menu-ancestor > a {  
color: #9cb770;  
font-weight: bold;  
}

Figura 1. Il menu di navigazione su desktop

 
Un menu a scomparsa, come il menu appena creato, non si adatta agli schermi touch dei dispositivi mobili, per questo sono
necessarie una o più media queries:
@media screen  and (max-width: 640px) {  
.primary-navigation ul {  
margin: 0;  
padding: 0;  
overflow: hidden;  
}  
.primary-navigation li {  
width: 100%;  
padding: 0;  
margin: 0;  
}  
.primary-navigation ul ul {  
display: block;  
}  
.primary-navigation ul ul ul {  
display: block;  
top: auto;  
left: auto;  
}  
.primary-navigation li ul {  
display: block;  
position: relative;  
}  
.primary-navigation .current_page_item > a,  
.primary-navigation .current-menu-item > a {  
   
}  
.primary-navigation .current_page_item > a:before,  
.primary-navigation .current-menu-item > a:before {  
content: " \27AF ";  
margin-right: .2em;  
}  
}

Gli elementi che vengono nascosti con la proprietà display: none, vengono resi sempre visibili sugli schermi di
larghezza superiore a 800px. Inoltre sono state adattate le dimensioni degli elementi delle liste, che andranno ad occupare
tutta la larghezza disponibile (width: 100%). Per rendere più chiara la navigazione, infine, si è aggiunta una freccia
verso destra alla voce corrente del menu (content: " \27AF "). L’immagine che segue mostra l’effetto a video.

Figura 2. Il menu di navigazione su uno schermo di larghezza inferiore a 640px


 
Conclusioni  e  riferimenti  

Si è, così, iniziato a progettare l’aspetto delle pagine. Va evidenziato che sono possibili molte alternative al menu
presentato, il cui scopo è, quindi, solo quello di fornire uno spunto per ulteriori analisi.

Per approfondire gli argomenti trattati in questo capitolo, si rinvia alle seguenti risorse:

• Funzione  body_class()    
• Funzione  wp_nav_menu()    
Il file style.css: i contenuti delle pagine
Terzo capitolo dedicato al file style.css. Nei precedenti si è definito il layout e si è analizzata nel dettaglio
l’intestazione delle pagine. Si è creato, inoltre, il menu di navigazione nello stile Suckerfish. In questo capitolo si vedrà
come assegnare gli stili alle pagine e ai post, per la parte che riguarda i testi e le immagini che costituiscono i contenuti,
nonché per la parte che riguarda i commenti dei lettori ed il form di risposta.

Le  classi  dei  post  

Così come il tag body_class() manda a video le classi del body, il tag post_class() stampa le classi dei singoli
post. Alcune di queste hanno valenza generale, come post o page. Altre sono più specifiche, come category-
{category-name} e tag-{tag-name}. Nel file allegato è disponibile l’elenco delle classi generate dalla funzione
post_class().

Nel tema che si sta sviluppando, i post sono racchiusi all’interno di un elemento article, che quindi sarà generato dalla
seguente stringa:

<article id="post-<?php the_ID(); ?>"  <?php post_class(); ?>>

Il markup inviato al browser sarà simile a quello che segue:

<article  id="post-90"  class="post-90 post type-post status-publish format-standard


hentry category-news">

I  contenuti  di  articoli  e  pagine  

Strutturalmente, un articolo si scompone in un’intestazione contenente il titolo, in un riassunto (se previsto), nel contenuto
principale e in un footer contenente meta-tag e commenti:

<article>  
<header  class="entry-header">  
<h1  class="entry-title">...</h1>  
</header>  
<div  class="entry-summary">...</div> <!-- conditional -->  
<div  class="entry-content">...</div>  
<footer  class="entry-meta">...</footer>  
</article>

In questa struttura, le classi non sono generate da WordPress, ma vengono aggiunte in fase di sviluppo nel template file.
Quelle che seguono sono alcune dichiarazioni che permettono di dar forma agli articoli:

.content-area article {  
margin-bottom: 4.2em;  
}  
.entry-header {  
margin-bottom: 1em;  
}  
.entry-title {  
font-size: 2.2em;  
margin-bottom: .5em;  
}  
.edit-link {  
display: inline-block;  
float: right;  
text-transform: uppercase;  
}  
.edit-link a {  
text-decoration: none;  
padding: 0  .6em;  
}  
.edit-link a {  
color: #397249;  
background-color: #ececec;  
}  
.edit-link a:hover {  
color: #9cb770;  
}  
.entry-summary {}  
.entry-content {}  
.entry-content a {  
text-decoration: underline;  
}  
.entry-meta {  
margin-top: 1.4em;  
}

Ovviamente queste dichiarazioni sono solo quelle essenziali, e in fase di sviluppo si dovranno definire con maggior
dettaglio gli stili degli elementi. Tuttavia bastano già a dare alla pagina un aspetto accettabile, come evidenziato
dall’immagine che segue.

Figura 1. Struttura iniziale del layout di pagina.


 
I  post  thumbnail  

Una funzionalità dei temi ad alto valore aggiunto è costituita dalle immagini in evidenza. Se il tema supporta i post
thumbnails, questi possono essere inseriti all’interno di vari template per dar risalto ai singoli post, con un’immagine di
dimensioni prestabilite. Nei prossimi capitoli si vedrà come attivare questa funzionalità, per ora si imposteranno solo gli stili
per le classi predefinite, che sono le seguenti:

.attachment-{size} {}  
.wp-post-image {}

size sta ad indicare le dimensioni impostate per l’immagine, che potrà essere post-thumbnail (nessuna dimensione
specificata), thumbnail, medium, large, full. Nel tema che si sta sviluppando, lo stile dell’immagine di anteprima
sarà il seguente:

.post-thumbnail img[class^=attachment] {  
float: left;  
margin: 0  1.2em  1.2em  0;  
}

A beneficio degli schermi di dimensioni inferiori sarà integrata la media query dichiarata nei precedenti capitoli:

@media screen  and (max-width: 640px) {  


...  
.entry-summary img[class^=attachment] {  
float: none;  
display: block;  
clear: both;  
}  
}

Il risultato a video è mostrato nell’immagine che segue.

Figura 2. Inserimento di un’immagine in evidenza.

 
Gli  stili  dell’editor  WYSIWYG  

Alcune classi vengono generate al momento della creazione dei contenuti nell’editor WYSIWYG. Queste classi permettono
di definire agevolmente l’allineamento degli elementi, la dimensione delle immagini, lo stile delle didascalie, e gran parte
del markup generato dall’editor.
Nel tema che si sta sviluppando vengono subito dichiarati i seguenti stili, necessari ad allineare gli elementi:

/* styles applied to containers and images (without captions) */  


.alignleft {  
float: left;  
}  
.alignright {  
float: right;  
}  
.aligncenter {  
display: block;  
margin-left: auto;  
margin-right: auto;  
}

Si provvede, poi, a definire alcuni stili delle immagini con didascalia:

.wp-caption  {  
margin-bottom: 2em;  
}  
.wp-caption  img[class*="wp-image-"] {  
display: block;  
margin: 0;  
}  
.wp-caption  {  
color: #397249;  
border: 2px  solid  #ececec;  
margin: 0  .4em;  
}  
.wp-caption-text {  
font-size: .8em;  
font-style: italic;  
line-height: 1.2em;  
margin: .6em  0  0;  
padding: .4em;  
text-align: center;  
background-color: #ececec;  
}  
.wp-smiley {  
margin: 0  !important;  
max-height: 1em;  
}

Queste poche dichiarazioni non completano l’aspetto degli articoli, eppure danno a post e pagine un look già ben definito.

Figura 3. Immagine con didascalia.


 
Dopo le immagini, una particolare attenzione va riposta all’elemento blockquote. Questo non viene automaticamente
associato ad una classe, tuttavia è sempre utile non dimenticare di definirne l’aspetto. Nel tema verranno inseriti seguenti
blocchi:

blockquote {  
background: rgba(199, 225, 186, 0.6);  
border: 1px  solid  rgba(57, 114, 73, 0.6);  
color: rgb(57, 114, 73);  
padding-left: .5em;  
quotes: "«"  "»";  
}  
blockquote::before {  
color: rgb(57, 114, 73);  
content: open-quote;  
font-size: 4em;  
line-height: 0.1em;  
margin-right: 0.25em;  
vertical-align: -0.4em;  
}  
blockquote p {  
margin: -1em  0  0  2em;  
padding: 0.5em  .7em  1em;  
}
Il risultato è nella figura che segue.

Figura 4. Stilizzazione dell’elemento Blockquote.

 
Le  gallerie  

Sono molteplici le classi associate da WordPress agli elementi che compongono le gallerie di immagini. Queste vengono
ospitate da una div di classe gallery, mentre le singole immagini saranno inserite in elementi figure o dl, a seconda
che il tema supporti o meno le gallerie in HTML5.
In precedenza sono stati dichiarati alcuni stili per le immagini; gli stessi stili valgono per le gallerie, il cui markup si
presenta genericamente come segue:

<div  id="gallery-1"  class="gallery galleryid-166 gallery-columns-3 gallery-size-


thumbnail">  
<dl  class="gallery-item">  
<dt  class="gallery-icon landscape">  
<a  href=".../lorem-ipsum-2/wp_512_draw/">  
<img  class="attachment-thumbnail"  src=".../img.png">  
</a>  
</dt>  
<dd  class="wp-caption-text gallery-caption"> Caption </dd>  
</dl>  
...

Come si vede, l’elemento img è assegnato da WordPress alla classe attachment-thumbnail, mentre l’elemento dd
viene assegnato alla classe wp-caption-text. Gli stessi stili dichiarati sopra per le immagini di anteprima, vengono
applicati, quindi, alle immagini organizzate in gallerie.

Figura 5. Galleria di immagini.


 
Negli schermi a dimensioni ridotte, le gallerie potrebbero essere visualizzate in modo non corretto. Si rende necessario,
quindi, renderle responsive con un attento lavoro di adattamento, oppure, più semplicemente, si può pensare di nasconderle
del tutto con una media query:

@media screen  and (max-width: 640px) {  


.gallery {  
display: none;  
}  
}

L’elenco completo delle classi generate da WordPress per le gallerie di immagini, come per tutti gli elementi generati
dall’editor WYSIWYG, è disponibile nel file in allegato al capitolo .

Commenti  

Se i commenti sono abilitati, al di sotto di ogni post o pagina viene visualizzato l’output del template comments.php. Il
markup generato rispetta la seguente struttura generale:

<div  id="comments"  class="comments-area">  


<h2  class="comments-title">...</h2>  
<ol  class="comment-list">  
<li  id="comment-2"  class="comment byuser comment-author-carlo bypostauthor
even thread-even depth-1 parent">  
<div  id="div-comment-2"  class="comment-body">...</div>  
<ol  class="children">...</ol>  
</li>  
</ol>  
<div  id="respond"  class="comment-respond">  
<h3  id="reply-title"  class="comment-reply-title">Lascia un Commento</h3>  
<form  id="commentform"  class="comment-form"  ... >  
...  
</form>  
</div>  
</div>

All’interno del form possono trovar posto un numero variabile di campi, a seconda che l’utente sia autenticato o meno.
Come si vede dal codice riportato, anche in questo caso gli elementi generati da WordPress vengono assegnati a classi
specifiche che ne permettono una facile selezione.
Tre soli blocchi di dichiarazioni e i commenti si distinguono nettamente dal resto della pagina:

.comment {  
padding: .4em;  
padding-left: 1em;  
font-size: .9rem;  
}  
.thread-even {  
background-color: #e9e9e9;  
}  
.comment-list .children {  
margin-left: 1em;  
}

Figura 6. La lista dei commenti.

 
Nel file CSS qui disponibile è riportato l’elenco completo dei selettori degli elementi che generano la struttura della
div.comments-area.

I  form  

Un lavoro più attento va svolto sui form, che potrebbero essere composti da un corposo set di elementi, tra cui i numerosi
input introdotti da HTML5. Nello sviluppo del tema di questa guida, si è fatto riferimento al foglio di stile dello starter
theme Underscore di Automattic. Il codice CSS che regola l’aspetto dei form è, dunque, il seguente:
button,  
input,  
select,  
textarea {  
font-size: 100%;  
margin: 0;  
vertical-align: baseline;  
}  
button,  
input[type="button"],  
input[type="reset"],  
input[type="submit"] {  
border: 1px  solid;  
border-color: #ccc  #ccc  #bbb;  
border-radius: 3px;  
background: #e6e6e6;  
box-shadow: inset  0  1px  0  rgba(255, 255, 255, 0.5), inset  0  15px  17px  rgba(255,
255, 255, 0.5), inset  0  -5px  12px  rgba(0, 0, 0, 0.05);  
color: rgba(0, 0, 0, .8);  
cursor: pointer;  
-webkit-appearance: button;  
font-size: 12px;  
font-size: 1.2rem;  
line-height: 1;  
padding: .6em  1em  .4em;  
text-shadow: 0  1px  0  rgba(255, 255, 255, 0.8);  
}  
button:hover,  
input[type="button"]:hover,  
input[type="reset"]:hover,  
input[type="submit"]:hover {  
border-color: #ccc  #bbb  #aaa;  
box-shadow: inset  0  1px  0  rgba(255, 255, 255, 0.8), inset  0  15px  17px  rgba(255,
255, 255, 0.8), inset  0  -5px  12px  rgba(0, 0, 0, 0.02);  
}  
button:focus,  
input[type="button"]:focus,  
input[type="reset"]:focus,  
input[type="submit"]:focus,  
button:active,  
input[type="button"]:active,  
input[type="reset"]:active,  
input[type="submit"]:active {  
border-color: #aaa  #bbb  #bbb;  
box-shadow: inset  0  -1px  0  rgba(255, 255, 255, 0.5), inset  0  2px  5px  rgba(0, 0, 0,
0.15);  
}  
input[type="checkbox"],  
input[type="radio"] {  
padding: 0; /* Addresses excess padding in IE8/9 */  
}  
input[type="search"] {  
-webkit-appearance: textfield;  
-webkit-box-sizing: content-box;  
-moz-box-sizing: content-box;  
box-sizing: content-box;  
}  
input[type="search"]::-webkit-search-decoration {  
-webkit-appearance: none;  
}  
button::-moz-focus-inner,  
input::-moz-focus-inner {  
border: 0;  
padding: 0;  
}  
input[type="text"],  
input[type="email"],  
input[type="url"],  
input[type="password"],  
input[type="search"],  
textarea {  
color: #666;  
border: 1px  solid  #ccc;  
border-radius: 3px;  
}  
input[type="text"]:focus,  
input[type="email"]:focus,  
input[type="url"]:focus,  
input[type="password"]:focus,  
input[type="search"]:focus,  
textarea:focus {  
color: #111;  
}  
input[type="text"],  
input[type="email"],  
input[type="url"],  
input[type="password"],  
input[type="search"] {  
padding: 3px;  
}  
textarea {  
overflow: auto;  
padding-left: 3px;  
vertical-align: top;  
width: 100%;  
}

Figura 7. Il form dei commenti.


 
Riferimenti  

Il lavoro sul foglio di stile non è ancora concluso, ma non manca molto. Nel prossimo capitolo si darà forma al sistema di
navigazione tra i post, alle sidebar con i rispettivi widget, e, infine, al footer delle pagine. In ultimo, si fornirà il foglio di
stile del tema in via di sviluppo ed un riferimento definitivo (e quasi completo) alle classi generate da WordPress.

Per concludere, si ricordano le risorse cui si è fatto riferimento in questo capitolo:

• L’oggetto  WP_Theme    
• CSS  Coding  Standard    
• Funzione  post_class()    
• Post  formats    
• Post  Thumbnails    
• TinyMCE    
• Progetto  Underscores,  disponibile  su  Github    

Il file style.css: elenchi, sidebar e widget


In questa lezione analizziamo le classi css che servono a dare forma a elenchi di pagine e tassonomie, sidebar e widget. Le
ultime dichiarazioni per completare il file style.css.

La  navigazione  delle  pagine  

Le funzioni di WordPress che producono mark-up sono diverse, alcune delle quali assegnano una o più classi agli elementi
generati. Tra queste, wp_page_menu genera una div di classe menu contenente la lista non ordinata delle pagine:

wp_page_menu( 'show_home=1&exclude=56&menu_class=page-navi&sort_column=menu_order'  
);
Tra i parametri passati alla funzione, menu_class permette di sovrascrivere la classe menu, assegnata di default al
container. L’output inviato al browser è strutturato come segue:

<div  class="page-navi">  
<ul>  
<li><a  href="http://example.com/">Home</a></li>  
<li  class="page_item page-item-2">  
<a  href="http://example.com/pagina-­‐di-­‐esempio/">Pagina di esempio</a>  
</li>  
<li  class="page_item page-item-4 current_page_item">  
<li  class="page_item page-item-4 page_item_has_children current_page_item">  
<a  href="http://example.com/nuova-­‐pagina/">Nuova Pagina</a>  
<ul  class="children">  
<li  class="page_item page-item-56">  
<a  href="http://example.com/nuova-­‐pagina/pagina-­‐figlio/">Pagina
figlio</a>  
</li>  
</ul>  
</li>  
   
</ul>  
</div>

Quello che segue è l’elenco delle classi generate da wp_page_menu:

.menu {} /* can be overwitten by menu_class parameter */  


.page_item {} /* single list item */  
.page-item-{id} {} /* specific list item */  
.page_item_has_children {} /* parent list item */  
.current_page_item {} /* active list item */  
.children {} /* unordered child list */

La funzione wp_list_pages genera una lista pressoché identica alla precedente, con la sola differenza che gli elementi
dell’elenco non vengono inseriti in una div, ma in un elemento li di classe pagenav:

<li  class="pagenav">  
Pagine  
<ul>  
...  
</ul>  
</li>

L’elenco completo dei selettori è reperibile nello "zip" allegato all’articolo .

Gli  elenchi  di  categorie  

Seguendo lo stesso schema degli elenchi di pagine, la funzione wp_list_categories genera un list item contenente
una o più liste annidate, i cui elementi individuano le categorie o qualsiasi tassonomia registrata. Queste le classi generate
dal framework:

.categories {} /* or any registered taxonomy */  


.cat-item {}  
.cat-item-{id} {}  
.current-cat {}  
.current-cat-parent {}  
.children {}

Se alla funzione wp_list_categories viene richiesta una tassonomia, al list item esterno sarà assegnato un nome di
classe corrispondente al nome della tassonomia.

Le  sidebar  e  i  widget  

Per WordPress una sidebar non è letteralmente una barra laterale, ma un’area destinata ad accogliere widget, ossia
blocchi di codice HTML generati dinamicamente. WordPress dispone di una dozzina di widget predefiniti, i quali generano
elenchi di categorie, articoli recenti, tag, pagine, menu personalizzati, ed altro ancora. Una sidebar viene inserita nel tema
grazie alla seguente funzione:

<?php dynamic_sidebar( 'sidebar-primary'  ); ?>

La funzione dynamic_sidebar() manda a video la sidebar-primary, che sarà definita più avanti nel file
functions.php. La sidebar così generata viene popolata di widget dalla pagina di amministrazione "Aspetto > Widget".
Ognuno di questi ha una precisa struttura HTML, e ai rispettivi elementi vengono assegnati classi e id che permettono di
selezionarli agevolmente.

Figura 1. I widget vengono aggiunti alla sidebar con una semplice operazione di drag & drop.

 
Due nomi di classe sono comuni a tutti i widget:

.widget {} /* widget container */  


.widgettitle {} /* widget title */

La prima classe viene assegnata alla div esterna, mentre la seconda all’elemento h2 che racchiude il titolo. Si deve
sottolineare che sia le classi widget e widgettitle, che l’elemento h2, possono essere sostituiti con nomi di classe ed
elementi HTML personalizzati, come si vedrà più avanti in questa guida. Alla div esterna, oltre alla classe widget, viene
assegnata una classe specifica per il tipo di widget:

.widget_categories {}  
.widget_recent_comments {}  
.widget_calendar {}  
.widget_recent_entries {}  
.widget_archive {}  
.widget_nav_menu {}  
.widget_pages {}  
.widget_text {}  
.widget_tag_cloud {}  
.widget_rss {}  
.widget_meta {}  
.widget_search {}

I contenuti dei widget vengono generalmente visualizzati all’interno di liste non ordinate, a meno che non si tratti di
elementi specifici, come il calendario e il box di ricerca. Per il tema "seventyone", che si sta sviluppando in questa guida,
sono state impostate le dimensioni generali dei widget con la seguente dichiarazione:

.widget {  
line-height: 2;  
margin-bottom: 2em;  
width: 100%;  
}

L’aspetto del calendario viene invece stabilito dai seguenti blocchi:

.widget_calendar table {  
width: 100%;  
line-height: 2;  
margin: 0;  
}  
.widget_calendar caption  {  
color: #fff;  
font-weight: 700;  
line-height: 1.7142857142;  
margin-bottom: 18px;  
text-align: left;  
text-transform: uppercase;  
}  
.widget_calendar tbody {  
border-bottom: 1px  solid  rgba(57, 114, 73, 0.6);  
border-top: 1px  solid  rgba(57, 114, 73, 0.6);  
}  
.widget_calendar tbody td,  
.widget_calendar thead th {  
text-align: center;  
}  
.widget_calendar tbody a {  
background-color: rgba(199, 225, 186, 0.6);  
display: block;  
}  
.widget_calendar tbody a:hover {  
background-color: #c7e1ba;  
color: #000;  
}  
.widget_calendar #prev {  
padding-left: 5px;  
}  
.widget_calendar #next {  
padding-right: 5px;  
text-align: right;  
}

Figura 2. Il widget Calendar.

 
Nel box di ricerca viene, infine, nascosto il pulsante di invio:

/* Search Widget*/  
.widget_search input[type="submit"] {  
visibility: hidden;  
display: none;  
}

Potrebbe sembrare che la progettazione delle sidebar, e soprattutto dei widget, comporti un gran lavoro di codifica CSS.
Eppure, a ben guardare, dal punto di vista strutturale i widget non si differenziano molto l’uno dall’altro. Il numero
consistente di classi potrà essere un utile strumento per rifinire e differenziare, ma l’aspetto base potrà essere definito con
dichiarazioni di carattere generale:

.widget li {} /* all list items */  


.widget li li {} /* nested list items */

Nello “zip” allegato è disponibile l’elenco completo dei selettori degli elementi che compongono i widget predefiniti.

Il  footer  

Il piè di pagina può ospitare diverse informazioni: un menu di navigazione alternativo, disclaimer e informazioni di
copyright, collegamenti a social network ed anche un form per un contatto rapido. Grazie ai widget, è possibile inserire e
modificare queste informazioni direttamente dal pannello di amministrazione. Chi sviluppa il tema potrà, quindi, prevedere
una nuova sidebar.

Figura 3. Aggiungere sidebar al tema dal pannello di amministrazione


 
Al foglio di stile si aggiungano, quindi, i due seguenti blocchi di dichiarazioni:

#footer-sidebar {  
border-bottom: 1px  solid  black;  
border-top: 1px  solid  black;  
overflow: hidden;  
width: 100%  
}  
   
#footer-sidebar .widget {  
margin-right: 0.52083335%;  
margin-left: 0.52083335%;  
padding: 0.52083335%;  
width: 22.9166666%;  
float: left;  
background-color: #eee;  
}

Gli elementi div.widget sono affiancati a sinistra con la proprietà float. Un problema dei layout basati sui float è che
i contenitori collassano su se stessi se non opportunamente progettati. In questo caso si è fatto ricorso ad una tecnica poco
nota, ma perfettamente cross-browser. Il primo blocco di dichiarazioni, quindi, permetterà al contenitore #footer-
sidebar di non collassare, e i blocchi interni ed esterni saranno resi correttamente. Il secondo blocco assegna le
dimensioni ai widget e li affianca l’uno all’altro.

Figura 4. Rendering del tema su Opera per (Mac) OS X


 
Nella figura qui sopra, i bordi della #footer-sidebar e gli sfondi dei widget hanno il solo scopo di evidenziare il
comportamento del browser, e possono essere resi nei colori più opportuni.

Rendere  responsive  la  sidebar  

L’ultimo task consiste nel rendere responsive la sidebar del footer. Se nel layout generale si è voluto dare ai singoli widget
una larghezza pari a circa il 25% dell’area disponibile, su schermi di dimensioni inferiori sarà opportuno ridimensionarli.
Ad esempio, se la finestra del browser ha una larghezza in pixel compresa tra i 640 e gli 800, i widget potrebbero occupare
ognuno la metà (circa) della larghezza del contenitore:

@media screen  and (min-width: 641px) and (max-width: 800px) {  


#site-footer {  
width: 100%;  
}  
   
#footer-sidebar .widget {  
width: 47.9166666%;  
float: left;  
}  
}

Figura 5. Sidebar a fondo pagina su Chrome in una finestra 800*640px


 
Infine, per gli schermi di dimensioni inferiori a 640px, ogni widget dovrà estendersi su tutta la larghezza disponibile:

@media screen  and (max-width: 640px) {  


...  
#sidebar {  
float: left;  
width: 100%;  
margin-right: 0;  
}  
   
#site-footer {  
width: 100%;  
}  
   
#footer-sidebar .widget {  
width: 97.9166666%;  
float: none;  
}  
...  
}

Figura 6. Sidebar a fondo pagina su Chrome in una finestra inferiore ai 640px


 
Il foglio di stile del tema seventyone è ora completo ed è disponibile nello "zip" allegato all’articolo dove sarà possibile
reperire anche l’elenco dei selettori descritti.
Riferimenti  

In questo capitolo si è fatto riferimento alle seguenti risorse:

• wp_page_menu  
• wp_list_pages  
• wp_list_categories  
• register_sidebar    
• Clearing  floats    

Il file index.php nei temi di WordPress


Il file index.php è il template principale (e l’unico indispensabile) di ogni tema di WordPress. La struttura del file deve
essere tale da generare ogni tipo di pagina, sia che si tratti del blog, che degli archivi di notizie, delle pagine statiche o anche
degli attachment. Si tratta di uno script composto da frammenti di codice HTML e istruzioni PHP, per gran parte
semplificate dalle funzioni del framework.

La  struttura  della  pagina  

Lo scopo del file index.php è quello di generare dinamicamente il mark-up delle pagine. In un tema estremamente
semplice, si può affidare questo compito al solo index.php; in un tema più complesso sarà necessario creare template ad-
hoc. Alcuni di questi generano la struttura generale della pagina (blog, archivio, pagina singola, ecc.), altri, invece, generano
il codice di specifiche parti.

Così i template header.php, sidebar.php e footer.php, saranno inclusi nel file index.php, e produrranno
rispettivamente il mark-up dell’intestazione, della sidebar e del fondo della pagina. Si supponga, quindi, che la struttura
della pagina sia così articolata:

<!-- File index.php -->  


   
<!-- File header.php -->  
<!doctype html>  
<html class="no-js"  lang="it-IT">  
<head>...</head>  
<body class="home blog">  
<div id="page"  class="site">  
<header id="site-header">  
<h1 class="site-title">...</h1>  
<nav id="primary-navigation">...</nav>  
</header>  
<!-- Fine file header.php -->  
   
<div id="main-content"  class="main-content">  
<div id="content"  class="content-area"  role="main">  
   
<!-- Template specifico -->  
<article>...<article>  
<!-- Fine template specifico -->  
   
</div>  
</div>  
   
<!-- File sidebar.php -->  
<aside id="sidebar">...</aside>  
<!-- Fine file sidebar.php -->  
   
<!-- File footer.php -->  
<footer id="site-footer">...</footer>  
</div><!-- #page -->  
</body>  
</html>  
<!-- Fine file footer.php -->  
   
<!-- Fine file index.php -->

I commenti evidenziano le parti della pagina delegate ai template specifici.

L’intestazione  del  file  index.php  

Anche se non è indispensabile, spesso il codice PHP del file index viene preceduto da meta-dati che forniscono alcune
informazioni generali sul template, come il nome del CMS, il nome e la versione del tema:

/**  
* @package WordPress  
* @subpackage Seventy-One-WordPress-Theme  
* @since Seventy One 1.0  
*/

Lo  script  del  file  index.php  

Subito dopo aver incluso l’header, il file index.php provvede a generare la parte principale della pagina, dove vengono
visualizzati i contenuti archiviati nella tabella wp_posts del database. In questa parte del documento, oltre ai contenuti,
vengono spesso inserite le categorie e le tassonomie associate agli articoli (tag e custom taxonomies). Quello che segue è lo
script completo del file index.php del tema “Seventyone”:

<?php get_header(); ?>  


<div id="main-content"  class="main-content">  
<div id="content"  class="content-area"  role="main">  
<?php  
if  (have_posts()) :  
// Start the Loop.  
while  (have_posts()) : the_post();  
/*  
* Include the post format-specific template for the content. If you
want to  
* use this in a child theme, then include a file called called
content-___.php  
* (where ___ is the post format) and that will be used instead.  
* from Twenty Fourteen  
*/  
get_template_part( 'content', get_post_format() );  
   
if( is_single() ) :  
comments_template();  
endif;  
   
endwhile;  
?>  
<?php post_navigation(); ?>  
<?php  
else  :  
// If no content, include the "No posts found" template.  
// from Twenty Fourteen  
get_template_part( 'content', 'none'  );  
endif;  
?>  
</div><!-- #content -->  
</div><!-- #main-content -->  
   
<?php get_sidebar(); ?>  
<?php get_footer(); ?>

L’intestazione  del  file  e  la  testata  del  documento  

La prima istruzione del file include il template header.php. Invece delle consuete funzioni include() e require(),
è consigliato utilizzare una funzione propria del framework di WordPress: get_header():

<?php get_header(); ?>

Il file header.php genera i tag di apertura del documento, <doctype> e <html>, il tag di apertura <head> e tutti i
meta tag; incorpora gli script e i fogli di stile e, infine, genera la parte superiore della pagina, ossia header e menu di
navigazione. Tale file header.php sarà analizzato dettagliatamente nel prossimo capitolo.

Il  contenuto  delle  pagine  

Il contenuto viene racchiuso nelle due div, #main-content e #content. Il blocco condizionale verifica l’esistenza di
post che corrispondono alla richiesta dell’utente e, in caso positivo, avvia un ciclo iterativo, definito Loop, che recupera dal
database gli articoli.

Le istruzioni interne al Loop dovranno generare l’output HTML. Queste istruzioni possono essere inserite direttamente nel
file index.php, oppure inserite in template specifici, incorporati nel file dalla funzione get_template_part. Nel
tema Seventyone è stato previsto di creare un template specifico per ogni formato di post.

Un  template  per  ogni  formato  di  post  

get_template_part incorpora quindi un template individuato dai due argomenti accettati dalla funzione:

get_template_part( $slug, $name  );


Argoment
Descrizione
o
$slug (string)  E’  il  nome  generico  del  template  (content  nel  codice  visto  sopra).
(string)  E’  il  nome  del  template  specifico,  che  nel  codice  riportato  sopra  è  
$name determinato  dalla  funzione  get_post_format(),  che  restituisce  il  formato  del  post  
corrente.

Per quanto detto, sarà necessario creare un template generico e tanti template specifici per quanti sono i formati di post
supportati dal tema. Pertanto bisognerà creare i seguenti file:

• content.php  
• content-aside.php  
• content-audio.php  
• content-gallery.php  
• content-image.php  
• content-link.php  
• content-none.php  
• content-quote.php  
• content-video.php  

Oltre al template generico content.php e ai template specifici per ogni formato, è stato previsto il template content-
none.php, che sarà incorporato nel file index.php nel caso in cui non siano presenti articoli corrispondenti alla
richiesta dell’utente. Quello che segue è il codice del file content.php del tema Seventyone:

<article id="post-<?php the_ID(); ?>"  <?php post_class(); ?>>  


<header class="entry-header">  
<?php  
if  ( is_single() ) :  
the_title( '<h1 class="entry-title">', '</h1>'  );  
else  :  
the_title( '<h1 class="entry-title"><a href="'  . esc_url(
get_permalink() ) . '" rel="bookmark">', '</a></h1>'  );  
endif;  
?>  
<?php posted_on(); ?>  
<?php edit_post_link( __( 'Edit', 'seventyone'  ), '<span class="edit-
link">', '</span>'  ); ?>  
</header>  
<?php if  ( is_search() || is_home() ) : ?>  
<div class="entry-summary">  
<?php  
if  ( has_post_thumbnail() ){  
?>  
<div class="post-thumbnail"><?php the_post_thumbnail( 'thumbnail'  
); ?></div>  
<?php  
}  
?>  
<?php the_excerpt(); ?>  
</div><!-- .entry-summary -->  
<?php else  : ?>  
<div class="entry-content">  
<?php the_content(); ?>  
</div>  
<footer class="entry-meta">  
<?php the_tags(__('Tags: ','seventyone'), ', ', '<br />'); ?>  
<?php _e('Posted in','seventyone'); ?> <?php the_category(', ') ?> |  
<?php  
if  ( comments_open() ) :  
comments_popup_link(__('No Comments &#187;','seventyone'), __('1 Comment
&#187;','seventyone'), __('% Comments &#187;','seventyone'));  
endif;  
?>  
</footer>  
<?php endif; ?>  
</article>

Tag, attributi e contenuti vengono generati dinamicamente, grazie ai template tags. Per sintetizzare l’analisi, lo stesso codice
sarà inserito in tutti i template content-{postformat}.php.
Il discorso sul file index.php è ampio e sarà esaurito nel proseguio della guida, quando esamineremo la prima versione
del tema “Seventyone”.

Il file index.php, funzioni, commenti, sidebar e


fondo pagina
Le  funzioni  dello  script  

Nello script appena visto si è più volte fatto ricorso alla funzione _e(): questa genera un testo corrispondente alla
traduzione della stringa passata come primo argomento (il secondo argomento definisce il textdomain dove recuperare la
traduzione). La funzione posted_on() non fa parte del framework, ma viene definita nel file functions.php come
segue:

function posted_on() { printf( __( '<span class="sep">Posted </span><a href="%1$s" title="%2$s"


rel="bookmark"><time class="entry-date" datetime="%3$s" pubdate>%4$s</time></a> by <span class="byline
author vcard">%5$s</span>', '' ), esc_url( get_permalink() ), esc_attr(
get_the_time() ), esc_attr( get_the_date( 'c' ) ), esc_html( get_the_date() ),
esc_attr( get_the_author() ) ); }

Oltre alle due funzioni riportate qui sopra, si è fatto ricorso a svariati tag del framework:

Tag Descrizione
Manda  a  video  una  stringa  con  l’ID  del  post  corrente;  va  utilizzata  
the_ID()
all’interno  del  Loop.
Manda  a  video  le  classi  associate  al  post  corrente;  questo  tag  può  
post_class()
essere  utilizzato  all’interno  o  all’esterno  del  Loop.
E’  un  conditional  tag  che  testa  se  la  pagina  corrente  sia  una  pagina  
is_single()
singola  (tipo  di  post,  pagina  o  allegato),  o  una  pagina  di  archivio.
Manda  a  video  o  restituisce  una  stringa  con  il  titolo  del  post  corrente;  
the_title()
va  utilizzata  all’interno  del  Loop.
Manda  a  video  un  link  alla  pagina  di  modifica  del  post  corrente;  può  
edit_post_link()
essere  utilizzata  all’interno  o  all’esterno  del  Loop.
E’  un  conditional  tag  che  testa  se  la  pagina  corrente  mostra  i  risultati  
is_search()
di  una  ricerca.
Testa  se  la  pagina  corrente  è  una  home  page  strutturata  come  blog  di  
is_home()
notizie.
Testa  se  il  post  corrente  dispone  di  un’immagine  di  anteprima;  va  
has_post_thumbnail()
utilizzata  all’interno  del  Loop.
Genera  il  codice  HTML  dell’immagine  di  anteprima;  va  utilizzata  nel  
the_post_thumbnail()
Loop.
the_excerpt() Mostra  il  riassunto  del  post  corrente;  va  utilizzata  nel  Loop.
the_content() Mostra  il  contenuto  del  post  corrente;  va  utilizzata  nel  Loop.
Genera  il  codice  HTML  dei  link  agli  archivi  dei  tag  associati  al  post  
the_tags()
corrente;  deve  essere  utilizzato  all’interno  del  Loop.
the_category() Genera  il  codice  HTML  dei  link  agli  archivi  delle  categorie  del  post  
corrente;  deve  essere  utilizzato  all’interno  del  Loop.
comments_open() Testa  se  per  il  post  o  per  la  pagina  corrente  i  commenti  sono  aperti.
Genera  un  link  alla  finestra  di  pop-­‐up  dei  commenti;  se  questa  non  è  
comments_popup_link()
attiva,  genera  un  normale  link  alla  lista  dei  commenti.

Un  template  per  le  pagine  senza  contenuti  

Nel caso in cui non esistano articoli corrispondenti alla richiesta dell’utente, viene incluso nel documento il template
content-none.php:

<header class="page-header"> <h1 class="page-title"><?php _e( 'Nothing Found',


'seventyone' ); ?></h1> </header> <div class="page-content"> <?php if (
is_home() && current_user_can( 'publish_posts' ) ) : ?> <p><?php printf( __(
'Publish your first post <a href="%1$s">here</a>.', 'seventyone' ), admin_url(
'post-new.php' ) ); ?></p> <?php elseif ( is_search() ) : ?> <p><?php _e(
'Nothing found. Please try again.', 'seventyone' ); ?></p> <?php
get_search_form(); ?> <?php else : ?> <p><?php _e( 'Nothing
found.', 'seventyone' ); ?></p> <?php get_search_form(); ?> <?php endif;
?> </div><!-- .page-content -->

Nella tabella che segue sono elencati i tag cui si è fatto ricorso:

Tag Descrizione
Testa  se  la  pagina  corrente  è  una  home  page  strutturata  come  blog  di  
is_home()
notizie.
current_user_can() Testa  se  l’utente  collegato  ha  i  privilegi  per  accedere  alla  risorsa  corrente.
Genera  un  link  al  pannello  di  amministrazione;  i  parametri  passati  come  
admin_url()
argomento  permettono  di  stabilire  la  pagina  specifica.
is_search() Testa  se  la  pagina  corrente  mostra  i  risultati  di  una  ricerca.
get_search_form() Manda  a  video  il  form  di  ricerca  generato  dal  template  file  searchform.php.

Anche qui, per la corretta localizzazione dei testi, si è fatto ricorso alla funzione _e().

I  commenti  

Qualora il blog/sito Web sia aperto ai commenti degli utenti, subito dopo la generazione del contenuto dell’articolo, sarà
necessario predisporre un’area dedicata in cui inserire il form e la lista dei commenti. Nel file index.php di
“Seventyone”, si è utilizzato il seguente blocco condizionale:

if( is_single() ) : comments_template(); endif;

Il conditional tag is_single() restituisce true qualora l’utente abbia richiesto un articolo o una pagina singola. Nel
caso in cui la condizione sia verificata, il template tag comments_template() incorpora nel documento il template file
comments.php, che sarà analizzato nel dettaglio nei prossimi capitoli.
La  navigazione  

Nel file index.php va predisposto anche un sistema di navigazione tra gli articoli del sito Web. Al di fuori del Loop
bisognerà inserire il codice che genera i link che puntano alle pagine precedenti e successive. Nel file index.php di
“Seventyone” viene invocata la funzione post_navigation():

<?php post_navigation(); ?>

Questa viene definita nel file functions.php:

function post_navigation() { echo '<div class="navigation">'; echo ' <div class="next-


posts">'.get_next_posts_link('&laquo; Older Entries').'</div>'; echo ' <div class="prev-
posts">'.get_previous_posts_link('Newer Entries &raquo;').'</div>'; echo '</div>'; }

Sidebar  e  fondo  pagina  

Il file index.php si conclude con altri due include tag:

<?php get_sidebar(); ?> <?php get_footer(); ?>

Seguendo la stessa logica del tag get_header(), queste ultime due funzioni includono nel documento i template
sidebar.php e footer.php. Il primo genera un’area widget; il secondo genera il fondo della pagina. I due template
saranno analizzati dettagliatamente nei prossimi capitoli.

Figura 1. Ciao Mondo!


 
Conclusioni  e  riferimenti  

Il file index.php non è costituito da uno script indipendente, ma da frammenti di codice distribuiti in diversi template
file, ognuno destinato a generare una parte specifica del documento. Nei prosimi capitoli si analizzeranno nel dettaglio i
template file che qui sono stati solo presentati, a cominciare dal file header.php.

Si rinvia al Codex per ogni informazione sui template tag e sulle altre funzioni del framework qui riportate. È utile
approfondire gli argomenti trattati tramite le seguenti risorse:

• The  Loop  
• I18n  for  WordPress  Developers  

In allegato al capitolo la prima versione del tema “Seventyone”.

Il file header.php nei temi


In un tema WordPress ogni pagina prevede un’intestazione, una parte centrale destinata ai contenuti, una o più sidebar, e,
infine, un fondo pagina. Il codice che genera queste aree può essere direttamente inserito nel template principale, oppure, in
template specifici, che vengono inclusi dinamicamente nel template principale. Il primo template specifico è il file
header.php, incluso nel template principale grazie al tag get_header.

La  struttura  dell’intestazione  

Lo script genera l’intestazione del documento HTML e la parte superiore della pagina. L’output comprenderà, quindi, il
doctype, i tag di apertura degli elementi html e body, nonché l’elemento head con i relativi meta tag, gli script e i
fogli di stile. Questi, naturalmente, possono essere inseriti direttamente nel documento o inclusi con gli elementi link e
script. Quello che segue è un esempio dell’intestazione generato dal file header.php:

<!doctype html>  
<html  class="no-js">  
<head>  
<meta  charset="UTF-8">  
<meta  name="viewport"  content="width=device-width, initial-scale=1">  
...  
<title>Seventyone | Un nuovo sito targato WordPress</title>  
<link  rel="stylesheet"  href="style.css"  />  
<script  src="/js/vendor/modernizr-2.8.3.min.js"></script>  
</head>

Lo script provvede anche a generare la parte superiore della pagina e il menu di navigazione principale. La struttura su cui si
svilupperà l’intestazione del tema Seventyone è la seguente:

<body  class="home blog">  


<div  id="page"  class="site">  
<header  id="site-header"  class="site-header"  role="banner">  
<a  class="home-link"  href="..."  title="Seventyone"  rel="home">  
<h1  class="site-title">Seventyone</h1>  
</a>  
<nav  id="primary-navigation"  class="site-navigation primary-navigation"  
role="navigation">  
<div  class="menu-main-menu-container">  
<ul  id="menu-main-menu"  class="nav-menu">  
<li  id="menu-item-143"  class="menu-item">  
<a  href="...">Home</a>  
</li>  
...  
</ul>  
</div>  
</nav>  
</header>

L’apertura  del  documento  

Una volta definita la struttura, si può procedere alla progettazione dello script. Esattamente come per il file index.php, le
istruzioni PHP e il codice HTML del file header.php sono precedute dai meta-dati che identificano il tema:

<?php  
/**  
* @package WordPress  
* @subpackage Seventy-One-WordPress-Theme  
* @since Seventy One 1.0  
*/  
?>

Subito dopo vanno generati il doctype e l’apertura dei tag <html> e <head>:

<!doctype html>  
<!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7" <?php
language_attributes(); ?>> <![endif]-->  
<!--[if IE 7]><html class="no-js lt-ie9 lt-ie8" <?php language_attributes(); ?>>
<![endif]-->  
<!--[if IE 8]><html class="no-js lt-ie9" <?php language_attributes(); ?>>
<![endif]-->  
<!--[if gt IE 8]><!--><html  class="no-js"  <?php language_attributes(); ?>> <!--
<![endif]-->  
<!-- the "no-js" class is for Modernizr. -->  
<head>

I tag condizionali permettono di definire un elemento html specifico per ogni versione di Internet Explorer. In questo
blocco di codice, l’unica istruzione PHP è data dalla funzione language_attributes(), che genera gli attributi
specifici per la lingua del sito.La classe no-js è, infine, richiesta dalla libreria Modernizr.

Si prosegue, quindi, con l’elemento head. Questo conterrà tutti i meta-tag del documento:

<head>  
<meta charset="<?php bloginfo('charset'); ?>">  
<meta name="viewport"  content="width=device-width, initial-scale=1">  
<meta name="title"  content="<?php wp_title( '|', true, 'right' ); ?>">  
<meta name="description"  content="<?php bloginfo('description'); ?>"  />  
...

Del template tag bloginfo()si è già detto nei capitoli precedenti: qui i parametri charset e description
forniscono la codifica e la descrizione del sito, come memorizzati nelle impostazioni generali e di lettura del pannello di
amministrazione. La funzione wp_title(), invece, genera il titolo del sito. Si passa, quindi, agli elementi title, link
e script:

<head>  
...  
<title><?php wp_title( '|', true, 'right'  ); ?></title>  
   
<link rel="profile"  href="http://gmpg.org/xfn/11">  
<link rel="pingback"  href="<?php bloginfo( 'pingback_url' ); ?>">  
   
<!-- <link rel="stylesheet"  href="<?php echo get_template_directory_uri();
?>/css/normalize.css"> -->  
<link rel="stylesheet"  href="<?php echo get_stylesheet_uri(); ?>"  />  
   
<!-- Lea Verou's Prefix Free, lets you use  only un-prefixed properties in yuor
CSS files -->  
<script src="<?php echo get_template_directory_uri();
?>/js/vendor/prefixfree.min.js"></script>  
   
<script src="<?php echo get_template_directory_uri(); ?>/js/vendor/modernizr-
2.8.3.min.js"></script>

Ancora una volta si è fatto ricorso alla funzione bloginfo(), cui è stato passato, questa volta, il parametro
pingback_url. Le funzioni get_template_directory_uri() e get_stylesheet_uri() forniscono due
dati diversi: la directory del tema corrente e l’URL del foglio di stile. Come si vede, nel tema Seventyone si fa ricorso al
foglio di stile normalize.css, allo script -prefix-free e alla libreria Modernizr.

Infine, subito prima del tag di chiusura </head>, va invocata la funzione wp_head(), che completa l’intestazione del
documento:

<head>  
...  
<?php wp_head(); ?>  
</head>

La  testata  della  pagina  

Chiuso il tag <head>, si va a generare la parte superiore della pagina. Viene aperto il tag <body> e creata l’a testata con il
menu di navigazione:

<body <?php body_class(); ?>>  


   
<div id="page"  class="site">  
   
<header id="site-header"  class="site-header"  role="banner">  
<a class="home-link"  href="<?php echo esc_url( home_url( '/' ) ); ?>"  
title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>"  rel="home">  
<h1 class="site-title"><?php bloginfo( 'name'  ); ?></h1>  
<h3 class="site-description"><?php bloginfo( 'description'  );
?></h3>  
</a>  
   
<nav id="primary-navigation"  class="site-navigation primary-navigation"  
role="navigation">  
<?php wp_nav_menu( array( 'theme_location'  => 'primary',
'menu_class'  => 'nav-menu'  ) ); ?>  
<!-- <?php get_search_form(); ?> -->  
</nav>  
</header>
La div#page fa da contenitore per l’intero contenuto della pagina. Questa viene aperta nel file header.php e sarà, poi,
chiusa nel file footer.php, allo stesso modo degli elementi html e body.

Il primo elemento discendente è un header, che contiene il titolo e la descrizione del sito in h1 e h3. L’header, inoltre,
contiene il menu di navigazione principale, racchiuso in un elemento nav. All’interno vengono invocate le funzioni
wp_nav_menu e get_search_form. La prima genera il menu di navigazione, strutturato come lista non ordinata di
elementi. Qualora siano presenti dei sottomenu, questi vengono strutturati nella forma di liste annidate, sicché un elemento
li di un menu sovraordinato diventa il parent di un sottomenu. La seconda funzione, infine, genera un form di ricerca.
Nella tabella che segue vengono elencate le funzioni del framework cui si è fatto riferimento nella progettazione del file
header.php del tema Seventyone.

Funzione Descrizione
language_attributes() Mostra  gli  attributi  specifici  della  lingua  del  sito.
Filtra  le  URL  codificando  i  caratteri  speciali,  elimina  caratteri  
esc_url() non  validi  o  pericolosi,  rimuove  le  URL  che  non  appartengono  a  
protocolli  noti.
wp_title() Mostra  o  recupera  il  titolo  del  sito.
bloginfo()
Mostra  a  video  informazioni  sul  sito  in  base  ai  parametri  passati  
come  argomenti.
get_bloginfo()
Restituisce  informazioni  sul  sito  in  base  ai  parametri  passati  
come  argomenti.
get_template_directory_uri() Restituisce  la  directory  in  cui  è  istallato  il  tema  corrente.
get_stylesheet_uri() Restituisce  l’URL  del  foglio  di  stile  del  tema  corrente.
wp_head() Genera  le  intestazioni  del  documento.
language_attributes() Manda  a  video  le  classi  associate  al  body.
wp_nav_menu()
Mostra  un  menu  di  navigazione  creato  nella  scheda  “Menus”  del  
pannello  di  amministrazione.
get_search_form() Mostra  un  form  di  ricerca.

Il  tag  get_header  

Si è detto che il file header.php viene incluso nel file index.php grazie all’include tag get_header(). Se al tag
non viene passato alcun argomento, la funzione include l’header.php generico; tuttavia è possibile creare un header
diverso per ogni tipo di pagina. Questo dovrà avere un nome composto dal prefisso header e da un suffisso che
individua il template: header-{slug}.php. Ad esempio, l’istruzione

<?php get_header( 'home'  ); ?>

Lo script includerà nel template corrente il file header-home.php. Predisponendo, quindi, template specifici, si
potranno differenziare gli header a seconda della pagina richiesta dall’utente. Come si vedrà nei prossimi capitoli, la stessa
logica può essere applicata ai template che generano le sidebar e il footer delle pagine.

Nel prossimo capitolo si analizzerà il template che genera la sidebar.

Sidebar, footer e area commenti


Oltre a quelli già indicati in precedenza, altri tre template file generano il markup di aree specifiche della pagina:
sidebar.php costruisce l’area destinata ai widget, ossia quei blocchi di codice che generano menu secondari, contenuti
esterni e informazioni correlate; footer.php genera il codice HTML della parte inferiore della pagina; comments.php
genera l’area dei commenti.

La  registrazione  delle  sidebar  

WordPress permette di creare più aree widget all’interno della stessa pagina, come anche di creare aree widget specifiche
per i diversi tipi di pagine disponibili in un tema. Prima di essere inserita nelle pagine, una sidebar va registrata nel file
functions.php, grazie alla funzione register_sidebar:

if  ( function_exists('register_sidebar'  )) {  
function  seventyone_widgets_init() {  
register_sidebar( array(  
'name'                    => __( 'Sidebar Widgets', 'seventyone'  ),  
'id'                        => 'sidebar-primary',  
'before_widget'  => '<div id="%1$s" class="widget %2$s">',  
'after_widget'    => '</div>',  
'before_title'    => '<h3 class="widget-title">',  
'after_title'      => '</h3>',  
) );  
register_sidebar( array(  
'name'                    => __( 'Sidebar Footer', 'seventyone'  ),  
'id'                        => 'sidebar-footer',  
'before_widget'  => '<div id="%1$s" class="widget %2$s">',  
'after_widget'    => '</div>',  
'before_title'    => '<h3 class="widget-title">',  
'after_title'      => '</h3>',  
) );  
}  
add_action( 'widgets_init', 'seventyone_widgets_init'  );  
}

register_sidebar viene eseguita all’occorrenza di un evento specifico, widget_init. La funzione registra la


sidebar e aggiunge il markup individuato dai parametri dell’array argomento. Lo script qui sopra registra due sidebar: la
principale sarà generata dal template sidebar.php, la secondaria sarà generata all’interno del footer.php.

Una  volta  registrate,  le  sidebar  appaiono  nel  menu  “Aspetto  →  Widget”  del  pannello  di  
amministrazione.    

Figura 1. Sidebar di WordPress


 
Il  template  sidebar.php  

Nel capitolo dedicato al file index.php, si è visto che sidebar.php viene incluso nel template principale dal tag
get_sidebar():

<?php get_sidebar( $name  ); ?>

L’argomento $name è facoltativo ed è costituito da una stringa che rappresenta il nome di un template specifico
sidebar-{$name}.php. Se non viene passato alcun argomento, la funzione include il template sidebar.php
principale, che nel tema Seventyone contiene il seguente script:

<aside id="sidebar">  
<?php if  ( is_active_sidebar( 'sidebar-primary'  ) ) : ?>  
<div id="primary-sidebar"  class="primary-sidebar widget-area"  
role="complementary">  
<?php dynamic_sidebar( 'sidebar-primary'  ); ?>  
</div><!-- #primary-sidebar -->  
<?php endif; ?>  
</aside>

Il conditional tag is_active_sidebar() verifica se una data sidebar sia attiva, ossia contenga widget. L’argomento
individua la sidebar da verificare, che nell’esempio, è la sidebar principale. Nel caso in cui sia presente almeno un widget,
viene generata la div#primary-sidebar e, quindi, invocata la funzione dynamic_sidebar(), che avvia le varie
callback che generano i widget. Anche quest’ultima funzione aspetta come argomento l’identificativo della sidebar.
Risulterà il seguente markup:

<aside id="sidebar">  
<div id="primary-sidebar"  class="primary-sidebar widget-area"  
role="complementary">  
<!-- widget -->  
<!-- widget -->  
<!-- widget -->  
</div><!-- #primary-sidebar -->  
</aside>

Il  template  footer.php  

footer.php, oltre a generare la parte inferiore della pagina, chiude i tag aperti nel file header.php. Anche questo file
viene incluso nel template principale da un tag specifico:

<?php get_footer( $name  ); ?>

L’argomento $name, come già visto per le funzioni get_header() e get_sidebar(), individua il nome del template
specifico footer-{$name}.php. In mancanza dell’argomento, get_footer() include il template generico. Il
footer.php del tema Seventyone contiene il seguente codice:

<footer id="site-footer"  class="site-footer"  role="contentinfo">  


<?php if  ( is_active_sidebar( 'sidebar-footer'  ) ) : ?>  
<div id="footer-sidebar"  class="footer-sidebar widget-area"  
role="complementary">  
<?php dynamic_sidebar( 'sidebar-footer'  ); ?>  
</div><!-- #primary-sidebar -->  
<?php endif; ?>  
<div class="site-info">  
<small>&copy;<?php echo  date("Y"); echo  " "; bloginfo('name');
?></small>  
</div>  
</footer>  
</div><!-- #page -->  
<?php wp_footer(); ?>  
</body>  
</html>

Il conditional tag is_active_sidebar verifica che la sidebar-footer sia registrata e contenga widget: in caso
positivo, viene generato il markup della seconda sidebar. Al di fuori del blocco condizionale, la div#site-info ospiterà
le informazioni di copyright.

Un ultimo tag, wp_footer(), va inserito "sempre" prima della chiusura del tag <body>. Questa funzione, tra l’altro,
genera gli script che molti plugin prevedono di includere nella parte inferiore del documento. Pertanto, per evitare che
alcuni plugin non funzionino correttamente, andrebbe sempre inserito.

Figura 2. Il footer del tema Seventyone


 
I  commenti  

Si torni ancora una volta al file index.php per individuare le seguenti tre righe di codice:

if( is_single() ) :  
comments_template();  
endif;

Il conditional tag is_single() verifica che l’utente abbia richiesto una pagina singola (post, pagina o custom post type).
Nel caso in cui la condizione sia verificata, il tag comments_template() include nella pagina lo script del file
comments.php. Questo genera la lista dei commenti, il sistema di navigazione e il form di trasmissione.

Per prima cosa, va verificato se il post sia protetto da password:

if  ( post_password_required() ) {  
return;  
}  
?>

Qualora il tag post_password_required() restituisse false, lo script sarebbe interrotto. Si apre quindi il container e
si genera il titolo dell’area dei commenti:

<div id="comments"  class="comments-area">  


<?php if  ( have_comments() ) : ?>  
<h2 class="comments-title">  
<?php  
printf( _n( 'One thought on &ldquo;%2$s&rdquo;', '%1$s thoughts on
&ldquo;%2$s&rdquo;', get_comments_number(), 'seventyone'  ),  
number_format_i18n( get_comments_number() ), get_the_title() );  
?>  
</h2>

Una volta verificato che esistano commenti (have_comments()), viene mandato a video un titolo h2. La funzione _n()
restituisce una stringa diversa a seconda che il valore di get_comments_number() sia o meno maggiore di uno;
number_format_i18n() formatta un numero in base alle impostazioni locali; infine, get_the_title() restituisce
il titolo del post. Il codice HTML generato è il seguente:

<div id="comments"  class="comments-area">  


<h2 class="comments-title">9 thoughts on &ldquo;Lorem ipsum dolor&rdquo;</h2>

Nella scheda di amministrazione “Impostazioni > Discussione” è possibile stabilire un numero massimo di commenti per
pagina. Bisognerà, per questo, prevedere un sistema di navigazione:

<?php if  ( get_comment_pages_count() > 1 && get_option( 'page_comments'  ) ) : ?>  


<nav id="comment-nav-above"  class="navigation comment-navigation"  role="navigation">  
<h1 class="screen-reader-text"><?php _e( 'Comment navigation', 'seventyone'  );
?></h1>  
<div class="nav-previous"><?php previous_comments_link( __( '&larr; Older
Comments', 'seventyone'  ) ); ?></div>  
<div class="nav-next"><?php next_comments_link( __( 'Newer Comments &rarr;',
'seventyone'  ) ); ?></div>  
</nav><!-- #comment-nav-above -->  
<?php endif; ?>

La funzione get_comment_pages_count() restituisce il numero di pagine in cui sono suddivisi i commenti, mentre
get_option( 'page_comments' ) restituisce 1 nel caso in cui i commenti sono suddivisi in pagine, 0 in caso
contrario. Il test, quindi, verifica che sia stata impostata la paginazione dei commenti. Viene, quindi, generato un elemento
nav destinato ad ospitare i link alla pagina precedente e alla pagina successiva.

Va, quindi, generata la lista dei commenti:

<ol class="comment-list">  
<?php  
wp_list_comments( array(  
'style'            => 'ol',  
'short_ping'  => true,  
'avatar_size'=> 34,  
) );  
?>  
</ol><!-- .comment-list -->

La funzione wp_list_comments() genera il codice HTML della lista, che sarà strutturata in base ai parametri
dell’array argomento:

• il  parametro  style  "deve"  corrispondere  all’elemento  container  (nell’esempio  qui  sopra  è  


un  elemento  ol);  
• short_ping  imposta  la  struttura  della  lista;  
• avatar_size,  infine,  stabilisce  le  dimensioni  dell’avatar  dell’autore.  

Dopo la lista, può essere opportuno riproporre il sistema di navigazione, per evitare che l’utente ritorni alla parte superiore
della pagina per sfogliare le pagine dei commenti.

Il template comments.php si chiude con il form:

<?php if  ( ! comments_open() ) : ?>  


<p class="no-comments"><?php _e( 'Comments are closed.', 'seventyone'  ); ?></p>  
<?php endif; ?>  
   
<?php endif; // have_comments() ?>  
   
<?php comment_form(); ?>  
   
</div><!-- #comments -->

Il tag comment_form() genera il markup necessario. La tabella che segue offre un riepilogo delle funzioni del
framework utilizzate.

Funzione Descrizione
comments_open() Verifica  se  i  commenti  sono  ammessi
comment_form() Genera  il  form  dei  commenti
have_comments() Verifica  se  esistono  per  il  post  corrente
Restituisce  una  stringa  corrispondente  al  primo  o  al  secondo  
_n()
argomento,  a  seconda  che  il  terzo  sia  uguale  o  superiore  a  1
get_comments_number() Restituisce  il  numero  dei  commenti  ad  un  dato  articolo
get_comment_pages_count() Calcola  il  numero  di  pagine  in  cui  sono  suddivisi  i  commenti
Preleva  il  valore  di  un’opzione  dal  database,  in  base  al  parametro  
get_option()
passato  come  argomento
Restituisce  il  titolo  di  un  articolo;  se  utilizzata  all’esterno  del  Loop  
get_the_title()
prevede  come  argomento  l’id  dell’articolo
Converte  un  numero  intero  in  un  formato  basato  sulle  
number_format_i18n()
impostazioni  locali
next_comments_link() Genera  il  link  alla  successiva  pagina  dei  commenti
previous_comments_link() Genera  il  link  alla  precedente  pagina  dei  commenti
wp_list_comments() Genera  la  lista  dei  commenti  in  base  ai  parametri  passati

Riferimenti  

Come sempre, si raccomanda un’attenta lettura delle risorse del Codex, con particolare attenzione alle funzioni presentate in
questo capitolo. Oltre a quelle già segnalate, si aggiungono due utili risorse per chi sviluppa temi:

• Sidebars  
• Option  Reference  

Il Loop nei temi di WordPress


Quando l’utente naviga tra le pagine di un sito, WordPress interpreta le richieste e individua il template più adatto per
visualizzare i contenuti presenti nel database. Il template stabilisce la query da eseguire sul database, e quindi quali articoli o
pagine mostrare all’utente.

Nel caso del file index.php, vengono generalmente richiesti i post più recenti, indipendentemente dalla categoria o dalle
etichette (tag) associate. Un archivio categoria, invece, è più specifico e mostrerà solo i post appartenenti alla categoria.

Il template single.php funziona esattamente allo stesso modo, con la sola particolarità che la query restituirà un result
set di un solo elemento. I post recuperati dal database sono disponibili nell’oggetto $posts e vengono gestiti tramite un
ciclo iterativo definito Loop. All’interno del ciclo, template tag, conditional tag e include tag permettono di accedere in
sicurezza ad ogni singola informazione associata ai post.
The  Loop  

La struttura base del Loop è la seguente:

if  (have_posts()) :  
while  (have_posts()) : the_post();  
...  
endwhile;  
else:  
...  
endif;

All’interno del Loop andranno inserite le istruzioni che permettono di visualizzare le informazioni recuperate dal database.
A questo scopo, come illustrato in precedenza, WordPress fornisce un gran numero di template tag. Quello che segue è un
Loop che genera le informazioni essenziali di ogni post:

<?php  
if  (have_posts()) :  
while  (have_posts()) : the_post(); ?>  
<article id="post-<?php the_ID(); ?>"  <?php post_class(); ?>>  
<header class="entry-header">  
<?php the_title( '<h1 class="entry-title"><a href="'  . esc_url(
get_permalink() ) . '" rel="bookmark">', '</a></h1>'  ); ?>  
</header>  
<div class="entry-content">  
<?php the_content(); ?>  
</div>  
<footer class="entry-meta">  
<?php the_tags(__('Tags: ','seventyone'), ', ', '<br />'); ?>  
<?php _e('Posted in','seventyone'); ?> <?php the_category(', ') ?> |  
<?php  
if  ( comments_open() ) :  
comments_popup_link(__('No Comments &#187;','seventyone'), __('1
Comment &#187;','seventyone'), __('% Comments &#187;','seventyone'));  
endif; ?>  
</footer>  
<?php endwhile;  
else: ?>  
<header class="page-header">  
<h1 class="page-title"><?php _e( 'Nothing Found', 'seventyone'  ); ?></h1>  
</header>  
<?php endif; ?>

Il Loop appena visto non è ancora completo, ma è sufficiente per comprendere come utilizzare i template tag. Quelli che
seguono sono i tag di uso più comune all’interno del Loop:

Funzione Descrizione
the_permalink() Mostra  la  URL  del  post  corrente  
the_title() Mostra  il  titolo  del  post
the_author() Mostra  il  display  name  dell’autore
the_time()  e  the_date() Mostrano  la  data  del  post
the_excerpt()  e  the_content() Mostrano  il  riassunto  e  il  contenuto  del  post
the_meta() Genera  una  lista  non  ordinata  dei  custom  field  associati  al  post
the_category()  e  the_tags() Generano  le  liste  delle  categorie  e  dei  tag  del  post

Queste funzioni non fanno altro che mandare a video i dati già disponibili nell’oggetto $post. Per una gestione più
avanzata del dati, può essere opportuno manipolarli via PHP prima che venga generato l’output HTML. A tal fine, come si
ricorderà, WordPress fornisce i tag get_, che restituiscono i dati come valori di variabili. Al posto del tag
the_category, ad esempio, si può ricorrere al tag get_the_category(), che restituisce l’elenco delle categorie del
post sotto forma di array:

<?php foreach  ( ( get_the_category() ) as  $cat  ) { ?>  


<li><?php echo  $category->cat_name; ?></li>  
<li><?php echo  $category->category_description; ?></li>  
<?php } ?>

Nell’elenco che segue sono riportati alcuni dei tag get_ di uso più comune:

• get_permalink  
• get_the_title  
• get_the_author  
• get_the_time  
• get_the_date  
• get_the_content  
• get_post_meta  
• get_metadata  
• get_the_category  
• get_the_tags  

Spesso è necessario testare una condizione prima di visualizzare i dati. Ciò avviene, ad esempio, quando l’utente stesso
richieda un post singolo invece di un archivio di articoli, oppure quando bisogna verificare che l’utente sia autenticato. I
conditional tag sono quelle funzioni del framework che, appunto, permettono di verificare specifiche condizioni, restituendo
true in caso di successo, false in caso contrario. Quello che segue è un elenco dei tag condizionali a cui probabilmente
si farà maggior ricorso:

Funzione Descrizione
is_home() Verifica  se  l’utente  ha  richiesto  la  home  page  del  sito
is_front_page() Verifica  se  la  pagina  iniziale  sia  un  post  o  una  pagina  statica
is_single() Verifica  se  la  richiesta  corrisponde  ad  un  post  o  una  pagina  singola
is_sticky()
Verifica  se  il  post  corrente  sia  stato  contrassegnato  come  post  in  
evidenza
is_category()  e   Verificano  se  la  richiesta  corrisponde  ad  una  pagina  d’archivio  di  una  
is_tag() categoria  o  di  un  tag
is_archive() Verifica  se  la  richiesta  corrisponde  ad  una  qualsiasi  pagina  di  archivio
is_search() Verifica  se  la  richiesta  corrisponde  al  risultato  di  una  ricerca
comments_open() Verifica  che  sul  post  corrente  siano  abilitati  i  commenti
is_user_logged_in() Verifica  che  l’utente  corrente  sia  autenticato

A questo punto dell’analisi, sarà ben chiaro il Loop del file index.php di Seventyone:

<?php  
if  (have_posts()) :  
// The Loop.  
while  (have_posts()) : the_post(); ?>  
   
<article id="post-<?php the_ID(); ?>"  <?php post_class(); ?>>  
<header class="entry-header">  
<?php  
if  ( is_single() ) :  
the_title( '<h1 class="entry-title">', '</h1>'  );  
else  :  
the_title( '<h1 class="entry-title"><a href="'  . esc_url(
get_permalink() ) . '" rel="bookmark">', '</a></h1>'  );  
endif;  
?>  
   
<?php posted_on(); ?>  
<?php edit_post_link( __( 'Edit', 'seventyone'  ), '<span
class="edit-link">', '</span>'  ); ?>  
</header>  
   
<?php if  ( is_search() || is_home() ) : ?>  
<div class="entry-summary">  
<?php  
if  ( has_post_thumbnail() ){  
?>  
<div class="post-thumbnail"><?php the_post_thumbnail(
'thumbnail'  ); ?></div>  
<?php  
}  
?>  
<?php the_excerpt(); ?>  
</div><!-- .entry-summary -->  
<?php else  : ?>  
   
<div class="entry-content">  
<?php the_content(); ?>  
</div>  
   
<footer class="entry-meta">  
<?php the_tags(__('Tags: ','seventyone'), ', ', '<br />'); ?>  
<?php _e('Posted in','seventyone'); ?> <?php the_category(', ') ?>
|  
<?php  
if  ( comments_open() ) :  
comments_popup_link(__('No Comments &#187;','seventyone'), __('1
Comment &#187;','seventyone'), __('% Comments &#187;','seventyone'));  
endif;  
?>  
</footer>  
   
<?php endif; ?>  
   
</article>  
<?php  
if( is_single() ) :  
comments_template();  
endif;  
   
endwhile;  
?>

La funzione posted_on() non fa parte del framework di WordPress, ma è stata definita nel file functions.php come
segue:

function  posted_on() {  
printf( __( '<span class="sep">Posted </span><a href="%1$s" title="%2$s"
rel="bookmark"><time class="entry-date" datetime="%3$s" pubdate>%4$s</time></a> by
<span class="byline author vcard">%5$s</span>', ''  ),  
esc_url( get_permalink() ),  
esc_attr( get_the_time() ),  
esc_attr( get_the_date( 'c'  ) ),  
esc_html( get_the_date() ),  
esc_attr( get_the_author() )  
);  
}

In questo modo viene mandato a video uno span con il permalink del post, la data di pubblicazione e il nome a video
dell’autore.

Parti  di  template  

Più avanti in questa guida, si vedrà che i template file possono diventare sempre più complessi, man mano che si
aggiungono funzionalità al tema o aumenta il numero di opzioni di configurazione. Per tenere in ordine il codice, può essere
quindi opportuno creare file che contengono parti di template.

Seguendo lo schema del tema "Twentyfourteen", in "Seventyone" si è creato un template per ogni formato di post
disponibile. Il codice PHP e HTML compreso all’interno del Loop viene quindi inserito nei template content-
{post_format}.php, mentre nel file index.php rimane il codice che segue:

<?php  
if  (have_posts()) :  
// The Loop.  
while  (have_posts()) : the_post();  
get_template_part( 'content', get_post_format() );  
   
if( is_single() ) :  
comments_template();  
endif;  
   
endwhile;  
?>

La funzione get_template_part() incorpora i template content-{post_format}.php, individuati dai due


argomenti trasmessi. Il primo di questi individua il prefisso, il secondo il suffisso del nome del template, ottenuto dal tag
get_post_format(). Chiude, quindi, il Loop del file index.php il seguente codice:

<?php  
post_navigation();  
else  :  
get_template_part( 'content', 'none'  );  
endif;  
?>
La  paginazione  

In un blog è sempre necessario offrire agli utenti la possibilità di scorrere tra le pagine del sito prevedendo un sistema di
paginazione. Il tag posts_nav_link() genera i link alla pagina precedente e alla pagina successiva di un archivio o di
una pagina singola. Per gestire l’output in modo preciso, il framework fornisce i tag previous_posts_link() e
next_posts_link(). I corrispondenti tag get_ restituiscono i link come valori gestibili via PHP. Quello che segue è il
sistema di paginazione di Seventyone:

function  post_navigation() {  
echo  '<div class="navigation">';  
echo  '<div class="next-posts">'  . get_next_posts_link( '&laquo; Older Entries'  )
. '</div>';  
echo  '<div class="prev-posts">'  . get_previous_posts_link( 'Newer Entries
&raquo;'  ) . '</div>';  
echo  '</div>';  
}

Anche nel caso della paginazione, si può decidere di scrivere il codice in un file a parte. Invece di utilizzare un "include
ta"g, in questo caso si è preferito definire la funzione post_navigation() nel file functions.php. Nel file
index.php e in ognuno dei template file del tema, al di sotto del Loop si inserirà la seguente istruzione:

<?php post_navigation(); ?>

Figura 1. Schema visivo del funzionamento del Loop


 
Conclusioni  e  riferimenti  

In questo capitolo si è visto come operare con le query predefinite. WordPress, però, permette di impostare query
personalizzate e creare Loop multipli, funzionalità queste che, per complessità e conoscenze necessarie, richiedono
maggiore spazio e che, quindi, analizzeremo approfonditamente in un capitolo successivo. Per introdurre il Loop si è fatto
riferimento alle seguenti risorse:

• Class  Reference:  WP_Query  


• Query  overview  
• The  Loop  
• The  Loop  in  action  
• Post  Formats  
Il template single.php nei temi di WordPress
La gerarchia dei template assegna un template file ad ogni tipo di pagina richiesta, sia essa una pagina di archivio, un post,
una pagina statica, o una pagina personalizzata. In questo capitolo vedremo a cosa serve e come creare il template che
permette di visualizzare un singolo post, cioè il template single.php, precisando che la stessa logica può essere estesa
a tutti i template che generano pagine singole, come il file che produce le pagine statiche (page.php).

Per visualizzare singoli articoli, WordPress sceglie il template secondo il seguente ordine:

single-{$post_type}.php  
single.php  
index.php

$post-type è un eventuale tipo di post personalizzato (ad esempio single-product.php o single-


event.php), di cui si discuterà nei prossimi capitoli. Nel caso in cui non fosse disponibile il template single.php,
WordPress cercherà il file index.php.

Lo  script  

Quello che segue è il codice del template single.php:

<?php  
/**  
* @package WordPress  
* @subpackage Seventy-One-WordPress-Theme  
* @since Seventy One 1.0  
*/  
get_header(); ?>  
<div id="main-content"  class="main-content">  
<div id="content"  class="content-area"  role="main">  
<?php  
if  (have_posts()) :  
// Start the Loop.  
while  (have_posts()) : the_post();  
   
get_template_part( 'content', get_post_format() );  
   
if  ( comments_open() || get_comments_number() ) {  
comments_template();  
}  
   
endwhile;  
?>  
<?php post_navigation(); ?>  
   
<?php  
else  :  
get_template_part( 'content', 'none'  );  
endif;  
?>  
</div><!-- #content -->  
</div><!-- #main-content -->  
<?php get_sidebar(); ?>  
<?php get_footer(); ?>
La struttura di base è esattamente la stessa del template index.php. Trattandosi di un articolo specifico, però, potrebbe
essere interessante aggiungere meta-informazioni che riguardano il post o l’argomento trattato.

Un  box  con  il  profilo  dell’autore  

Soprattutto quando partecipano più utenti alla creazione dei contenuti, potrebbe essere una buona idea quella di aggiungere
alle pagine dei singoli articoli un box con una serie di informazioni sull’autore. Si supponga di voler dare al box la seguente
struttura:

<aside  class="author-box">  
<img  alt=""  src="...">  
<h4>About carlo</h4>  
<p>...<br  />  
<a  href="...">View all posts by ... (...)</a>  
</p>  
</aside>

Trattandosi di informazioni a margine del contenuto principale, per generare il box si ricorre ad un elemento aside.
All’interno sarà collocata l’icona del profilo utente, il nome dell’autore, la descrizione, il link all’archivio personale e il
numero di articoli pubblicati. Tutte queste informazioni saranno recuperate dal database grazie alle funzioni del framework
di WordPress. Data la struttura, si può progettare l’aspetto del box, aggiungendo le seguenti dichiarazioni al file
style.css:

/*  
5.5 – Other stuff  
*/  
   
.author-box{  
margin-top: 2.08334%;  
padding: 1.04167%;  
width: 100%;  
overflow: hidden;  
border: 2px  solid  #e8e8e8;  
background-color: #eee;  
}  
   
.author-box .avatar {  
float: left;  
margin-right: 1.04167%;  
}

In precedenza si è già presentato il codice del file single.php e a questo non si apporterà alcuna modifica. Si supponga
ora di voler aggiungere il box autore solo agli articoli di formato standard. L’unico template da modificare sarà il file
content.php. Si apra, quindi, il file e si vada direttamente alla chiusura dell’elemento article:

<?php endif; ?>  


<?php  
if( is_single() )  
get_template_part( 'template_parts/template', 'author'  );  
?>  
</article>

La condizione è necessaria in quanto il template content.php viene caricato per generare il contenuto sia delle pagine
singole che delle pagine di archivio. Quindi, qualora l’utente si trovi in una pagina singola, sarà caricato il template parziale
template-author.php, che si collocherà in una directory ad-hoc che può essere nominata template_parts.
Quello che segue è il codice del template.
<?php  
/**  
* @package WordPress  
* @subpackage Seventy-One-WordPress-Theme  
* @since Seventy One 1.0  
*/  
?>  
<aside class="author-box">  
<?php echo  get_avatar( get_the_author_meta( 'ID'  ) ); ?>  
<h4><?php echo  __('About ') . get_the_author_meta( 'display_name'  ); ?></h4>  
<p>  
<?php the_author_meta( 'description'  ); ?><br />  
<a href="<?php echo get_author_posts_url( get_the_author_meta( 'ID' ) );
?>">  
<?php echo  __('View all posts by ') . get_the_author() . ' ('  .
get_the_author_posts() .')'; ?>  
</a>  
</p>  
</aside>

L’elemento img dell’icona viene generato grazie alla funzione del framework get_avatar(). Questa recupera l’avatar
dell’utente a partire dall’ID o dall’indirizzo email. All’interno del Loop, l’ID viene recuperato grazie alla funzione
get_the_author_meta(). Questa stessa funzione viene invocata più volte: la prima volta viene passato come
argomento il parametro ID, la seconda volta il parametro display_name, infine ancora l’ID. Ogni volta la funzione
restituisce l’informazione corrispondente.

get_the_author_meta restituisce una stringa gestibile via PHP. Gli stessi dati possono essere mandati a video grazie
al corrispondente tag the_author_meta, qui invocato per stampare la descrizione dell’autore. L’URL del successivo
link viene generata dalla funzione get_author_posts_url, alla quale viene passato l’ID dell’autore.

Il testo del link, infine, viene generato dalla funzione get_the_author, che restituisce il display_name dell’autore
allo stesso modo di get_the_author_meta( 'display_name' ), e da get_the_author_posts, che
restituisce il numero degli articoli pubblicati dallo stesso autore. Nell’immagine che segue, il risultato a video.

Figura 1. Box autore


 
Oltre a quelle utilizzate in questo esempio, WordPress dispone di diverse altre funzioni che recuperano dal database
informazioni sugli autori. Quelle di uso più frequente sono riportate nella tabella che segue:

Funzione Descrizione
get_the_author() Restituisce  il  display_name  dell’autore  del  post  corrente
get_author_posts_url() Restituisce  la  URL  della  pagina  d’archivio  dell’autore
the_author_posts_link() Manda  a  video  un  link  che  punta  all’archivio  dell’autore

get_avatar()
Restituisce  una  stringa  in  cui  è  rappresentato  l’elemento  img  che  
genera  l’icona  di  un  utente
the_author_meta()
Manda  a  video  i  dati  riferiti  all’autore  in  base  ai  parametri  passati  
come  argomenti
get_the_author_meta()
Restituisce  i  dati  riferiti  all’autore  in  base  ai  parametri  passati  come  
argomenti
the_author_posts() Manda  a  video  il  numero  di  post  dell’autore
get_the_author_posts() Restituisce  il  numero  di  post  dell’autore

Progettare  una  struttura  ordinata  

Si è visto che il template parziale template-author.php è stato collocato in una directory specifica, cui è stato
assegnato il nome di template_parts. Ciò non sarebbe necessario se il tema mantenesse nel tempo una struttura
semplice e composta di pochi file. Può capitare, però, che un tema inizialmente semplice, aumenti via via di complessità. In
questo caso, si corre il rischio di ritrovarsi con una struttura disordinata e difficile da gestire. Si consiglia, quindi, di
strutturare in modo rigoroso il tema anche nel caso in cui si componga di pochi file essenziali. Quella che segue è la
struttura attuale del tema Seventyone.

Figura 2. Struttura tema

 
Conclusioni  e  riferimenti  

Quando si modifica il file style.css, potrebbe succedere che le modifiche non siano visibili. Dato che in questo capitolo
sono state aggiunte alcune dichiarazioni al foglio di stile, è opportuno disabilitare la cache del browser per verificare i
risultati a video.

Per ogni utile approfondimento, si suggeriscono le seguenti risorse:

• Class  Reference:  Template  Hierarchy  


• Post  formats  
• The  Loop  
 

Potrebbero piacerti anche