Comment puis-je générer un menu personnalisé/système de sous-menu en utilisant wp get nav éléments de menu dans wordpress?

j'ai une structure html qui nécessite la personnalisation du code wp_nav_menu .

C'est le html que je dois générer:

<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>

j'utilise actuellement wp_get_nav_menu_items pour obtenir tous les éléments de mon menu comme un tableau.

en ce moment je suis capable de générer le html ci-dessus sans les sous-menus en utilisant le code suivant:

<?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; ?>

j'aurais j'ai généré le menu en utilisant la fonction wp_nav_menu mais j'ai encore besoin de la description affichée en utilisant $page->post_excerpt .

j'ai trouvé qu'il y a une propriété pour chaque élément appelé $item->menu_item_parent qui donne L'ID de l'élément de menu parent.

comment générer le sous-menu de ma boucle foreach ? Ou y a-t-il un moyen très simple d'utiliser wp_nav_menu que Google a oublié de mentionner?

38
demandé sur hitautodestruct 2012-08-13 17:37:43

3 réponses

pour quiconque aborde quelque chose de similaire voici ma solution:

exemple de code rapide sur un gist

voici le code sur un GitHub gist pour quiconque veut entrer dans l'action copier coller.

TL; DR

TL;Dr boucle sur la liste, Forez vers le bas s'il y a un sous-menu, Fermer si nous atteignons la fin du sous-menu et le menu.

Code Complet explication

tout D'abord obtenir les éléments de menu comme un tableau plat:

<?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' ) );
?>

puis itérer sur le tableau des éléments de menu:

<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;
    ?>

écrire le premier élément parent <li> :

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

vérifier que l'id parent de ces articles correspond à l'id parent stocké:

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

démarrer le sous-menu <ul> et mettre le drapeau $submenu à true pour plus tard référence:

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

écrivez l'article du sous-menu:

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

si l'élément suivant n'a pas le même ID parent et que nous avons un sous-menu déclaré alors fermez le sous-menu <ul>

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

        <?php endif; ?>

de nouveau, si l'article suivant dans le tableau n'a pas le même ID parent fermer le <li>

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

<?php $count++; endforeach; ?>

  </ul>
</nav>
59
répondu hitautodestruct 2015-03-31 13:28:02

Votre meilleur pari est de faire votre propre Walker classe d'adapter la sortie à vos besoins. Quelque chose comme ceci:

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 );
    }
}

et appelez ça comme ça:

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

tout avant et après le marqueur obtenir L'extrait dans mon exemple était une copie directe de la fonction start_el dans wp-includes/nav-menu-template.php. Mon exemple utilise WP_Query pour déterminer si le post / page a un extrait, et place l'extrait entre les balises de portée après le titre du lien.

une idée serait de faire apparaître les étiquettes de portée seulement en vol stationnaire, ce qui peut être fait en utilisant CSS.

plus d'informations sur Walkers here:

WP Nav Menu Codex

Utilisant La Classe De Marchette

un autre exemple décent utilisant la classe de marcheur

9
répondu maiorano84 2017-04-13 12:37:31
      //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>
0
répondu GAJENDRA patel 2017-03-28 06:12:27