Descriere pentru elementele de meniu? Walker personalizat pentru wp_nav_menu()
Un meniu WordPress normal arată așa:
Acasă | Blog | Despre noi | Contact
Dar am văzut multe pagini cu descrieri sub aceste link-uri:
Acasă | Blogurile noastre | Despre noi | Contact
...vizitează-ne...| citește mai mult| informații de bază| formular de contact
Cum se poate realiza acest lucru?
(Vreau să fie o funcție de bază pentru toate temele mele, deci fără plugin-uri vă rog, vreau doar să știu cum se face)

Ai nevoie de un walker personalizat pentru meniul de navigare.
Practic, adaugi un parametru 'walker'
la opțiunile wp_nav_menu()
și apelezi o instanță a unei clase îmbunătățite:
wp_nav_menu(
array (
'menu' => 'main-menu',
'container' => FALSE,
'container_id' => FALSE,
'menu_class' => '',
'menu_id' => FALSE,
'depth' => 1,
'walker' => new Description_Walker
)
);
Clasa Description_Walker
extinde Walker_Nav_Menu
și modifică funcția start_el( &$output, $item, $depth, $args )
pentru a căuta $item->description
.
Un exemplu de bază:
/**
* Creează o listă HTML de elemente de meniu de navigare.
* Înlocuiește Walker-ul nativ, folosind descrierea.
*
* @see https://wordpress.stackexchange.com/q/14037/
* @author fuxia
*/
class Description_Walker extends Walker_Nav_Menu
{
/**
* Începe generarea elementului.
*
* @param string $output Trimis prin referință. Folosit pentru a adăuga conținut suplimentar.
* @param object $item Obiect de date al elementului de meniu.
* @param int $depth Adâncimea elementului de meniu. Poate fi folosită pentru padding.
* @param array|object $args Șiruri suplimentare. De fapt, întotdeauna o
instanță a stdClass. Dar acesta este WordPress.
* @return void
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )
{
$classes = empty ( $item->classes ) ? array () : (array) $item->classes;
$class_names = join(
' '
, apply_filters(
'nav_menu_css_class'
, array_filter( $classes ), $item
)
);
! empty ( $class_names )
and $class_names = ' class="'. esc_attr( $class_names ) . '"';
$output .= "<li id='menu-item-$item->ID' $class_names>";
$attributes = '';
! empty( $item->attr_title )
and $attributes .= ' title="' . esc_attr( $item->attr_title ) .'"';
! empty( $item->target )
and $attributes .= ' target="' . esc_attr( $item->target ) .'"';
! empty( $item->xfn )
and $attributes .= ' rel="' . esc_attr( $item->xfn ) .'"';
! empty( $item->url )
and $attributes .= ' href="' . esc_attr( $item->url ) .'"';
// inserează descrierea doar pentru elementele de nivel superior
// poți modifica acest aspect
$description = ( ! empty ( $item->description ) and 0 == $depth )
? '<small class="nav_desc">' . esc_attr( $item->description ) . '</small>' : '';
$title = apply_filters( 'the_title', $item->title, $item->ID );
$item_output = $args->before
. "<a $attributes>"
. $args->link_before
. $title
. '</a> '
. $args->link_after
. $description
. $args->after;
// Deoarece $output este trimis prin referință, nu este nevoie să returnăm nimic.
$output .= apply_filters(
'walker_nav_menu_start_el'
, $item_output
, $item
, $depth
, $args
);
}
}
Sau, alternativ cum a comentat @nevvermind, poți moșteni toate funcționalitățile funcției start_el
a părintelui și doar să adaugi descrierea la $output
:
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )
{
parent::start_el( $output, $item, $depth, $args );
$output .= sprintf(
'<i>%s</i>',
esc_html( $item->description )
);
}
Exemplu de rezultat:
Acum activează câmpul de descriere în wp-admin/nav-menus.php
pentru a putea edita acest câmp. Dacă nu faci asta, WP va arunca întregul conținut al postării în el.
Lecturi suplimentare:
- Bug-uri asociate
- Exemplu similar cu markup și formatare diferită
- Activează caseta de descriere în ecranul de gestionare a meniurilor programatic
- Colectează descrierea elementului pentru utilizare ulterioară
Și asta e tot.

Dacă pentru tine moștenirea != rescrierea întregii metode, ci doar păstrarea aceluiași nume, încearcă asta: public function start_el(&$output, $item, $depth, $args)
{
parent::start_el($output, $item, $depth, $args);
$output .= sprintf('<i>%s</i>', esc_html($item->description));
}

@nevvermind Ar trebui măcar să verifici dacă descrierea conține ceva. ;) Poziția descrierii în exemplul meu este doar cea mai simplă modalitate de a ilustra soluția. Dacă trebuie să adaugi descrierea în anchor, trebuie să reconstruiești întreaga funcție.

da, ar trebui să rescrii întreaga metodă, fără îndoială, dar pentru cei care au nevoie să (să zicem...) adauge ceva la ea, acest lucru le-ar putea salva de multe dureri de cap. Și toată vina este a WP. Arrrgh!

Foarte bun și l-am folosit în acest răspuns modificându-l puțin, poate poți să-l îmbunătățești dacă am ratat ceva, mulțumesc.

Începând cu WordPress 3.0, nu mai este nevoie de un walker personalizat!
Există filtrul walker_nav_menu_start_el
, vezi https://developer.wordpress.org/reference/hooks/walker_nav_menu_start_el/
Exemplu:
function add_description_to_menu($item_output, $item, $depth, $args) {
if (strlen($item->description) > 0 ) {
// adăugăm descrierea după link
$item_output .= sprintf('<span class="description">%s</span>', esc_html($item->description));
// sau.. inserăm descrierea ca ultim element în interiorul link-ului ($item_output se termină cu "</a>{$args->after}")
// $item_output = substr($item_output, 0, -strlen("</a>{$args->after}")) . sprintf('<span class="description">%s</span >', esc_html($item->description)) . "</a>{$args->after}";
}
return $item_output;
}
add_filter('walker_nav_menu_start_el', 'add_description_to_menu', 10, 4);

Acest lucru nu este mai bun sau mai rău decât alte sugestii; este doar diferit. Este scurt și la obiect.
În loc să folosești câmpul de descriere așa cum sugerează @toscho, ai putea completa câmpul "Titlu" pentru fiecare element de meniu cu textul dorit, apoi să folosești acest CSS:
.menu-item a:after { content: attr(title); }
De asemenea, ar fi ușor să folosești jQuery pentru a-l adăuga, dar întrucât textul este mai mult decorativ, CSS pare mai potrivit.
