Da un punto di vista strutturale, per WordPress un menu di navigazione è una semplice lista non ordinata di collegamenti ipertestuali. Naturalmente, esigenze specifiche di sviluppo possono richiedere la creazione di menu complessi, per i quali la struttura predefinita non è sufficiente. A partire da WordPress 3 è, però, possibile personalizzare i menu predefiniti in modo avanzato e senza grandi difficoltà.
Il framework permette infatti di creare sistemi di navigazione alternativi, mega-menu, ed elenchi arricchiti da elementi grafici non gestibili con i soli fogli di stile.
Aggiungere un menu ad un tema di WordPress
Quando si sviluppa o si modifica un tema, per inserire un menu in una specifica area della pagina, bisogna eseguire due operazioni: per prima cosa il menu va registrato nel file functions.php
, grazie alla funzione register_nav_menu
:
function register_my_custom_menu() {
register_nav_menu( 'custom', __( 'Custom Menu' ) );
}
add_action( 'init', 'register_my_custom_menu' );
Una volta registrato, il menu appare nel pannello di amministrazione, nell'elenco delle posizioni del tema.
La seconda operazione consiste nella collocazione del menu nell'area della pagina stabilita. La funzione wp_nav_menu
genera l'output HTML, composto da una semplice lista non ordinata. Per creare un menu di navigazione personalizzato, bisogna invocare wp_nav_menu
all'interno del file header.php
.
La funzione accetta come argomento un array di parametri, strutturato come segue:
$defaults = array(
'theme_location' => '',
'menu' => '',
'container' => 'div',
'container_class' => '',
'container_id' => '',
'menu_class' => 'menu',
'menu_id' => '',
'echo' => true,
'fallback_cb' => 'wp_page_menu',
'before' => '',
'after' => '',
'link_before' => '',
'link_after' => '',
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
'depth' => 0,
'walker' => ''
);
Il parametro theme_location
imposta la posizione del menu, già registrata nel file functions.php
con register_nav_menu
, e gestita dal pannello di amministrazione (Aspetto → Menu).
Il parametro menu
permette di associare manualmente il menu alla posizione stabilita in theme_location
: se non impostato, questo viene gestito nel pannello di amministrazione.container
imposta invece il contenitore della lista del menu: l'impostazione predefinita prevede una div
, ma potrebbe essere un elemento nav
o section
, o essere anche del tutto assente.
Il parametro items_wrap
imposta il contenitore dei singoli elementi, mentre depth
stabilisce il numero di liste annidate possibili, ossia i livelli di sottomenu ammessi.
Il parametro walker
, infine, imposta la classe che itera tra le voci del menu per generare l'output a video. Lasciando invariato il valore predefinito, la classe Walker_Nav_Menu
genera le singole voci così come create dall'amministratore.
Un semplice esempio: un menu di navigazione personalizzato
Se il "Custom Menu"è stato correttamente registrato nel file functions.php
, potrà essere richiamato in qualsiasi parte del tema. Per un menu di navigazione, la funzione wp_nav_menu
può essere invocata nel template header.php
, come nella seguente istruzione:
<?php wp_nav_menu(
array( 'theme_location' => 'custom',
'container_class' =>'custom',
'menu_class' => 'nav-menu' ) ); ?>
In questo esempio, alla funzione vengono passati solo i parametri theme_location
, container_class
e menu_class
. Viene generato, quindi, il seguente output:
<div class="custom">
<ul id="menu-main-menu" class="nav-menu">
<li id=" … " class="menu-item … ">
…
</ul>
Le proprietà avanzate dei menu
Le impostazioni predefinite di WordPress permettono di inserire una quantità limitata di dati, cioè quelli indispensabili alla struttura predefinita del menu di navigazione.
È, però, possibile aumentare i campi a disposizione, in modo da associare una maggiore quantità di informazioni ad ogni singola voce di menu. Nella scheda "Impostazioni schermata", infatti, si stabilisce cosa visualizzare nel pannello di amministrazione dei menu ("Aspetto → Menu").
Spuntando tutte le voci disponibili sarà possibile associare classi specifiche ai singoli elementi del menu, stabilire la relazione tra i link, la destinazione e la descrizione del collegamento.
WordPress offre, quindi, la possibilità di inserire i dati necessari a generare un menu complesso. Tuttavia, molti dei dati qui inseriti non vengono visualizzati. Un menu che si discosta dalla struttura predefinita, infatti, va riprogrammato estendendo la classe Walker
.
Un esempio avanzato: la classe Walker e la struttura del menu
La classe Walker
di WordPress è una classe astratta che itera tra gli elementi di una qualsiasi struttura in cui essi siano organizzati gerarchicamente, proprio come avviene in un menu.
Per generare un menu di navigazione, WordPress dispone della classe Walker_Nav_Menu
, che di per sé è già un'estensione di Walker
. Estendendo quest'ultima classe, diventa possibile modificare la struttura del menu principale, o crearne di nuovi.
La classe Walker
dispone di quattro metodi astratti che devono essere definiti nelle sue estensioni:
Metodo | Descrizione |
---|---|
start_lvl | apre il tag che definisce il contenitore del menu (es. <ul> ); |
end_lvl | chiude il tag aperto da start_lvl (es. </ul> ); |
start_el | apre il tag che individua il singolo elemento del menu (es. <li> ); |
end_el | chiude il tag precedente (es. </li> ); |
Per modificare la struttura del "Custom menu"; bisogna, quindi, estendere la classe Walker_Nav_Menu
e ridefinire i suoi metodi (la classe è definita nel file nav-menu-template.php
, presente nella directory wp-includes
).
Una semplice modifica alla struttura potrebbe essere quella dell'aggiunta della descrizione degli elementi di primo livello. Per effettuare questa modifica bisognerà definire una nuova classe che estenda Walker_Nav_Menu
e ridefinisca il metodo start_el
. Nel file functions.php
del tema (o del child theme) si dovrà aggiungere il seguente codice:
class custom_walker extends Walker_Nav_Menu{
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$indent = ( $depth ) ? str_repeat( "t", $depth ) : '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li' . $id . $value . $class_names .'>';
$atts = array();
$atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
$atts['target'] = ! empty( $item->target ) ? $item->target : '';
$atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : '';
$atts['href'] = ! empty( $item->url ) ? $item->url : '';
$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args );
$attributes = '';
foreach ( $atts as $attr => $value ) {
if ( ! empty( $value ) ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
/** Memorizza la descrizione dell'elemento del menu nella variabile $description */
$description = ! empty( $item->description ) ? '<span class="item-description">'.esc_attr( $item->description ).'</span>' : '';
if( $depth != 0 ){
$description = "";
}
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
/** This filter is documented in wp-includes/post-template.php */
/** aggiunge il valore di $description prima della chiusura del tag <a> */
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $description . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
Confrontando questo listato con quello presente nel file nav-menu-template.php
, si noterà che è stata instanziata una nuova variabile, $description
. Questa terrà in memoria una stringa composta dal tag <span>
e dalla descrizione della voce di menu inserita dall'amministratore. Nel file header.php
andrà aggiunto alla funzione wp_nav_menu
il parametro walker
:
<?php wp_nav_menu( array(
'theme_location' => 'custom',
'container_class' =>'custom',
'menu_class' => 'nav-menu',
'walker' => new custom_walker() ) ); ?>
Rimane da dare uno stile all'elemento span.item-description
nel foglio di stile del tema:
.item-description{
display: block;
padding-top: 6px;
font-style: italics;
font-size: small;
}
La descrizione verrà visualizzata al di sotto dell'etichetta degli elementi di primo livello.
Riferimenti online
Dunque estendendo la classe Walker
è possibile apportare ogni tipo di modifica alla struttura predefinita dei menu. Il riferimento obbligato per approfondire l'argomento è il codex di wordpress.org. Da qui si potranno agevolmente raggiungere tutte le risorse cui si è fatto riferimento in questo articolo.
Il codice completo è disponibile in allegato all'articolo.