wp_nav_menu wp_get_nav_menu_items mostrar example container code php wordpress menu wordpress-theming submenu

php - mostrar - ¿Cómo puedo generar un sistema de menú/submenú personalizado usando wp_get_nav_menu_items en wordpress?



wp_nav_menu example (3)

Para cualquiera que aborde algo similar, aquí está mi solución:

Ejemplo de código rápido en una esencia

Aquí está el código en una github gist para cualquiera que quiera entrar en la acción de copiar y pegar.

TL; DR

TL; DR Loop over list, profundizar si hay un submenú, cerrar si llegamos al final del sub menú y menú.

Completa la explicación del código

Primero, obtenga los elementos del menú como una matriz plana:

<?php $menu_name = ''main_nav''; $locations = get_nav_menu_locations(); $menu = wp_get_nav_menu_object( $locations[ $menu_name ] ); $menuitems = wp_get_nav_menu_items( $menu->term_id, array( ''order'' => ''DESC'' ) ); ?>

A continuación, itere sobre la matriz de elementos del menú:

<nav> <ul class="main-nav"> <?php $count = 0; $submenu = false; foreach( $menuitems as $item ): // set up title and url $title = $item->title; $link = $item->url; // item does not have a parent so menu_item_parent equals 0 (false) if ( !$item->menu_item_parent ): // save this id for later comparison with sub-menu items $parent_id = $item->ID; ?>

Escriba el primer elemento principal <li> :

<li class="item"> <a href="<?php echo $link; ?>" class="title"> <?php echo $title; ?> </a> <?php endif; ?>

Verifique que la identificación principal de estos elementos coincida con la ID padre almacenada:

<?php if ( $parent_id == $item->menu_item_parent ): ?>

Inicie el submenú <ul> y configure el indicador $submenu en verdadero para su posterior referencia:

<?php if ( !$submenu ): $submenu = true; ?> <ul class="sub-menu"> <?php endif; ?>

Escribe el elemento del submenú:

<li class="item"> <a href="<?php echo $link; ?>" class="title"><?php echo $title; ?></a> </li>

Si el siguiente elemento no tiene la misma identificación principal y tenemos un submenú declarado, cierre el submenú <ul>

<?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ): ?> </ul> <?php $submenu = false; endif; ?> <?php endif; ?>

De nuevo, si el siguiente elemento de la matriz no tiene el mismo ID principal, cierre el <li>

<?php if ( $menuitems[ $count + 1 ]->menu_item_parent != $parent_id ): ?> </li> <?php $submenu = false; endif; ?> <?php $count++; endforeach; ?> </ul> </nav>

Tengo una estructura html que requiere la personalización del código wp_nav_menu .

Este es el html que necesito generar:

<ul class="main-nav"> <li class="item"> <a href="http://example.com/?p=123" class="title">Title</a> <a href="http://example.com/?p=123" class="desc">Description</a> <ul class="sub-menu"> <li class="item"> <a href="http://example.com/?p=123" class="title">Title</a> <a href="http://example.com/?p=123" class="desc">Description</a> </li> </ul> </li> <li class="item"> <a href="http://example.com/?p=123" class="title">Title</a> <a href="http://example.com/?p=123" class="desc">Description</a> </li> </ul>

Actualmente estoy usando wp_get_nav_menu_items para obtener todos los elementos de mi menú como una matriz.

Ahora mismo puedo generar el html anterior sin los submenús usando el siguiente código:

<?php $menu_name = ''main-nav''; $locations = get_nav_menu_locations() $menu = wp_get_nav_menu_object( $locations[ $menu_name ] ); $menuitems = wp_get_nav_menu_items( $menu->term_id, array( ''order'' => ''DESC'' ) ); foreach ( $menuitems as $item ): $id = get_post_meta( $item->ID, ''_menu_item_object_id'', true ); $page = get_page( $id ); $link = get_page_link( $id ); ?> <li class="item"> <a href="<?php echo $link; ?>" class="title"> <?php echo $page->post_title; ?> </a> <a href="<?php echo $link; ?>" class="desc"> <?php echo $page->post_excerpt; ?> </a> </li> <?php endforeach; ?>

Hubiera generado el menú usando la función wp_nav_menu , pero aún necesito la descripción que se muestra usando $page->post_excerpt .

Descubrí que hay una propiedad para cada elemento llamada $item->menu_item_parent que proporciona el ID del elemento del menú principal.

¿Cómo generaría el submenú en mi ciclo foreach ? ¿O hay una forma realmente simple de usar wp_nav_menu que Google olvidó mencionar?


Su mejor opción es crear su propia clase de Walker para adaptar la salida a sus necesidades. Algo como esto:

class Excerpt_Walker extends Walker_Nav_Menu { function start_el(&$output, $item, $depth, $args) { global $wp_query; $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="'' . esc_attr( $class_names ) . ''"''; $id = apply_filters( ''nav_menu_item_id'', ''menu-item-''. $item->ID, $item, $args ); $id = strlen( $id ) ? '' id="'' . esc_attr( $id ) . ''"'' : ''''; $output .= $indent . ''<li'' . $id . $value . $class_names .''>''; $attributes = ! empty( $item->attr_title ) ? '' title="'' . esc_attr( $item->attr_title ) .''"'' : ''''; $attributes .= ! empty( $item->target ) ? '' target="'' . esc_attr( $item->target ) .''"'' : ''''; $attributes .= ! empty( $item->xfn ) ? '' rel="'' . esc_attr( $item->xfn ) .''"'' : ''''; $attributes .= ! empty( $item->url ) ? '' href="'' . esc_attr( $item->url ) .''"'' : ''''; $item_output = $args->before; $item_output .= ''<a''. $attributes .''>''; $item_output .= $args->link_before . apply_filters( ''the_title'', $item->title, $item->ID ) . $args->link_after; /*GET THE EXCERPT*/ $q = new WP_Query(array(''post__in''=>$item->object_id)); if($q->have_posts()) : while($q->have_posts()) : $q->the_post(); $item_output .= ''<span class="menu-excerpt">''.get_the_excerpt().''</span>''; endwhile;endif; /*****************/ $item_output .= ''</a>''; $item_output .= $args->after; $output .= apply_filters( ''walker_nav_menu_start_el'', $item_output, $item, $depth, $args ); } }

Y luego llámalo así:

<?php wp_nav_menu(array(''walker'' => new Excerpt_Walker())); ?>

Todo lo anterior y posterior al marcador GET THE EXCERPT en mi ejemplo era una copia directa de la función start_el en wp-includes / nav-menu-template.php. Mi ejemplo usa WP_Query para determinar si la publicación / página tiene un extracto, y coloca el extracto entre las etiquetas span después del título del enlace.

Una idea sería hacer que las etiquetas de span aparezcan solo al pasar el mouse, lo que se puede hacer usando CSS.

Más información sobre Walkers aquí:

WP Nav Menu Codex

Usando la clase de Walker

Otro ejemplo decente usando la clase Walker


//Just set your variable and apply.. for sub menu <ul> <?php $activeclass = ''''; $activeclass1=''''; $count=0; $submenu = FALSE; foreach ( $primaryNav as $navItem ) { $activeclass = ''''; if($navItem->object_id == $getid){ $activeclass = ''class="live-act"''; } if (!$navItem->menu_item_parent ){ $parent_id = $navItem->ID; echo ''<li><a href="''.$navItem->url.''" ''.$activeclass.'' title="''.$navItem->title.''">''.$navItem->title.''</a>''; } ?> <?php if ( $parent_id == $navItem->menu_item_parent ) { ?> <?php if ( !$submenu ): $submenu = true; ?> <ul> <?php endif; ?> <li> <a href="<?php echo $navItem->url; ?>" class="title"><?php echo $navItem->title; ?></a> </li> <?php if ( $primaryNav[ $count + 1 ]->menu_item_parent != $parent_id && $submenu ){ ?> </ul> <?php $submenu = false; } ?> <?php } if ( $primaryNav[ $count + 1 ]->menu_item_parent != $parent_id ){ ?> </li> <?php $submenu = false; } ?> <?php $count++; ?> <?php } ?> </ul>