Filtro wp_nav_menu ()


9

Cerco di dividere la mia navigazione in 3 singole barre di navigazione (livello 1, livello 2 e livello3 +). Tre perché sono separati sul sito e dovrebbero apparire solo in base alla pagina corrente.

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

La prima barra di navigazione contenente il livello 1 è sempre visibile. La seconda barra di navigazione (livello 2) solo quando sono attualmente nella pagina padre corrispondente. Lo stesso vale per la terza barra di navigazione (livello 3+, in più perché questa barra di navigazione conterrà anche pagine secondarie e pagine secondarie ... di livello 3).

In breve: voglio visualizzare tutti i menu principali nella barra di navigazione e solo i figli diretti della pagina corrente.

Cosa ho provato:

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

Chiamandolo nel mio header.php: <?php my_nav_menu( array( 'echo' => false , 'navlevel' => 1 ) ); ?>

Tuttavia $argsè impostato sui valori predefiniti e la mia voce personalizzata navlevelnon viene mostrata nel filtro.

Come posso dividere la mia barra di navigazione come descritto? Come posso impostare il mio $argsinserimento personalizzato ?


2
Buona giornata e benvenuti al WPSE. Devo congratularmi con te per l'epica domanda costruita per il primo cronometro. Le domande ben costruite che sono chiare ricevono sempre molta attenzione con buone risposte. +1
Pieter Goosen

3
La risposta a questo implica una classe Walker personalizzata, forse questo aiuterà tutti i potenziali risponditori
Tom J Nowell

Grazie. Ho scavato in php / wp solo questo fine settimana, quindi non sono così familiare. Ho provato un Walker personalizzato, tuttavia Walker gestisce solo un singolo oggetto alla volta, quindi non posso confrontarlo con l'articolo corrente. E un filtro non accetta il mio argomento personalizzato. Hmmm ...
nonsensation

Risposte:


3

Penso di aver ottenuto la risposta:

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

Questo fa il trucco: mi permette di modificare i menu e gli argomenti personalizzati sono ancora disponibili. Ho accidentalmente agganciato il filtro wp_get_nav_menu_itemsinvece di wp_nav_menu_objects. Ho ancora problemi con il filtro, tuttavia questi sono probabilmente alcuni bug logici ..

EDIT: risolverò il mio problema combinando navbar livello 2 e navbar livello 3+ in uno e separandoli con css

ecco l'attuale parte php:

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

Mi sembra a prima vista. Hai problemi con quel codice? Sidenote: puoi abbreviare la tua prima affermazione:$echo = ! isset( $args['echo'] ) ?: $args['echo'];
kaiser

1

Mi sembra che potresti gestirlo tramite CSS in quanto potresti nascondere le opzioni di menu di livello inferiore per impostazione predefinita e quindi scegliere di mostrarle se hanno determinate classi sopra di esse.

In questa pagina del Codex , puoi vedere le classi di menu (e sulla tua stessa pagina). Quindi per il "secondo livello" che hai descritto, supponendo che il menu di primo livello sia il livello 1 - non 0.

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

E poi qualcosa di simile per il prossimo livello in basso:

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

Ovviamente sostituisci "blocco" con "blocco in linea" o qualunque sia il tuo menu normalmente impostato.

Potrebbe essere necessario giocare per trovare la giusta combinazione di classi, ma prima ho avuto fortuna con questo metodo. WP lascia cadere un sacco di classi lì, potrebbe anche usarle.


Grazie, userò alcune lezioni in CSS per le mie barre di navigazione! :)
nonsensazione

Se hai finito con questa soluzione, potresti contrassegnare la mia risposta come accettata? Grazie.
Amanda Giles,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.