web-dev-qa-db-fra.com

Filtre wp_nav_menu ()

J'essaie de diviser ma navigation en 3 barres de navigation simples (niveau 1, niveau 2 et niveau 3 +). Trois parce qu'ils sont séparés sur le site et qu'ils ne devraient apparaître qu'en fonction de la page en cours.

-0-------1--------2-------3+- level/depth
Home
 |
 |\___ Lobby
 |
 |\___ Projects
 |       |\___ Project A
 |       |       |\___ Review
 |       |       |\___ Comments
 |       |       \____ Download
 |       \____ Project B
 |               |\___ Review
 |               |\___ Comments
 |               \____ Download
 |\___ Blog
 |
 \____ About
         |\___ Legal
         \____ Contact

La première barre de navigation contenant le niveau 1 est toujours visible. La deuxième barre de navigation (niveau 2) uniquement lorsque vous êtes actuellement sur la page parent correspondante. Il en va de même pour la troisième barre de navigation (niveau 3+, car cette barre de navigation contiendra également des sous-pages et des sous-pages ... de niveau 3).

En bref: je veux afficher tous les menus parents dans leurs barres de navigation et uniquement les enfants directs de la page en cours.

Ce que j'ai essayé:

function my_nav_menu( $args = array() )
{
    $echo = isset( $args['echo'] ) ? (bool)( $args['echo'] ) : true;
    $args['echo'] = false;

    add_filter( 'wp_get_nav_menu_items' , 'my_nav_menu_filter' , 666 , 3 );

    $menu = wp_nav_menu( $args );

    remove_filter( 'wp_nav_menu_objects' , 'my_nav_menu_filter' , 666 );

    if( $echo )
        echo $menu;
    else
        return $menu;
}

function my_nav_menu_filter( $items , $menu , $args )
{
    //var_dump( $args );

    $navLevel = isset( $args['navlevel'] ) ? (int)( $args['navlevel'] ) : 0;

    //echo 'navlevel = ' . $args['navlevel'] . ' | ' . $navLevel;

    if( $navLevel == 1 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
                unset( $items[$key] );
        }
    }
    else if( $navLevel == 2 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
            {
                $page = get_page( $item->menu_item_parent );

                if( $page->menu_item_parent == 0 )
                    continue;
            }

            unset( $items[$key] );
        }
    }
    else if( $navLevel == 3 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
            {
                $page = get_page( $item->menu_item_parent );

                if( $page->menu_item_parent != 0 )
                    continue;
            }

            unset( $items[$key] );
        }
    }
    else
    {
        //var_dump( $items );
    }

    return $items;
}

Appeler cela dans mon header.php: <?php my_nav_menu( array( 'echo' => false , 'navlevel' => 1 ) ); ?>

Cependant, $args est défini sur les valeurs par défaut et mon entrée personnalisée navlevel n'est pas affichée dans le filtre.

Comment puis-je diviser ma barre de navigation comme décrit? Comment définir mon entrée $args- personnalisée?

9
nonsensation

Je pense avoir la réponse:

function my_nav_menu( $args = array() )
{
    $echo = isset( $args['echo'] ) ? (bool)( $args['echo'] ) : true;

    $args['echo'] = false;

    add_filter( 'wp_nav_menu_objects' , 'my_filter_nav_menu' , 100 , 2 );

    $menu = wp_nav_menu( $args );

    remove_filter( 'wp_nav_menu_objects' , 'my_filter_nav_menu' , 100, 2 );

    if( $echo )
        echo $menu;
    else
        return $menu;
}

Cela fait l'affaire: permettez-moi de modifier les paramètres et les arguments personnalisés sont toujours disponibles. J'ai accidentellement accroché le filtre dans wp_get_nav_menu_items au lieu de wp_nav_menu_objects. J'ai encore des problèmes avec le filtrage, cependant ce sont probablement des bugs logiques.

EDIT: je résous mon problème en combinant les barres de navigation niveau 2 et niveau 3+ en les séparant avec css

voici la partie php actuelle:

function serthy_filter_nav_menu( $items , $args )
{
    $argArray = (array)( $args );

    if( isset( $argArray['toplevel'] ) )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
                unset( $items[$key] );
        }

        return $items;
    }

    global $post;

    $arr = array();

    foreach( $items as $key => $item )
    {
        $parentIDs = get_post_ancestors( $item->ID );

        foreach( $parentIDs as $i => $parentID )
        {
            if( $parentID == $post->ID )
            {
                array_Push( $arr , $item );

                break;
            }
        }
    }

    return $arr;
}
3
nonsensation

Il me semble que vous pouvez gérer cela via CSS en vous permettant de hide les options de menu de niveau inférieur par défaut, puis de choisir show leur s'ils ont certaines classes au-dessus d'eux.

Sur cette page Codex , vous pouvez voir les classes de menu (et sur votre page elle-même). Donc, pour le "deuxième niveau" que vous avez décrit, en supposant que le menu de premier niveau est le niveau 1 - pas 0.

ul > li > ul.sub-menu { display: none; }  /* Hide by default */
ul > li.current-menu-parent > ul.sub-menu { display: block; } /* Show menu */

Et puis quelque chose de similaire pour le niveau suivant:

ul > li > ul.sub-menu > li > ul.sub-menu{ display: none; }  /* Hide by default */
ul > li > ul.sub-menu > li.current-menu-parent > ul.sub-menu { display: block; }

Évidemment, remplacez "block" par "inline-block" ou tout autre réglage de vos menus.

Vous devrez peut-être jouer pour trouver la bonne combinaison de cours, mais cette méthode m'a déjà porté chance. WP y dépose une tonne de classes, autant les utiliser.

1
Amanda Giles