Filtruj wp_nav_menu ()

9

Staram się podzielić nawigację na 3 pojedyncze paski nawigacyjne (poziom 1, poziom 2 i poziom 3 +). Trzy, ponieważ są oddzielone w witrynie i powinny się pojawiać tylko w zależności od bieżącej strony.

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

Pierwszy pasek nawigacyjny zawierający poziom 1 jest zawsze widoczny. Drugi pasek nawigacyjny (poziom 2) tylko wtedy, gdy jestem aktualnie na odpowiedniej stronie nadrzędnej. To samo dotyczy trzeciego paska nawigacyjnego (poziom 3+, plus, ponieważ ten pasek nawigacyjny będzie również zawierał strony podrzędne i strony podrzędne ... poziomu 3).

W skrócie: Chcę wyświetlić wszystkie menu nadrzędne w ich paskach nawigacyjnych i tylko bezpośrednie elementy potomne bieżącej strony.

Co próbowałem:

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

Wywołanie tego w moim header.php: <?php my_nav_menu( array( 'echo' => false , 'navlevel' => 1 ) ); ?>

Jednak $argssą ustawione na wartości domyślne i mój niestandardowy wpis navlevelnie jest wyświetlany w filtrze.

Jak mogę podzielić pasek nawigacyjny zgodnie z opisem? Jak ustawić niestandardową $argspozycję?

nonsensation
źródło
2
Dzień dobry i witamy w WPSE. Muszę pogratulować ci epickiego pytania po raz pierwszy. Dobrze skonstruowane, przejrzyste pytania zawsze przyciągają uwagę dobrymi odpowiedziami. +1
Pieter Goosen
3
Odpowiedź na to pytanie dotyczy niestandardowej klasy Walkera, być może pomoże to potencjalnym użytkownikom
Tom J Nowell
Dziękuję Ci. Zagłębiłem się w php / wp tylko w ten weekend, więc nie jestem taki znajomy. Wypróbowałem niestandardowego Walkera, jednak Walker obsługuje tylko jeden element na raz, więc nie mogę go porównać z bieżącym przedmiotem. Filtr nie przyjmuje mojego niestandardowego argumentu. Hmmm ...
nonsens

Odpowiedzi:

3

Myślę, że mam odpowiedź:

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

To załatwia sprawę: pozwala mi zmieniać menuitems, a niestandardowe argumenty są nadal dostępne. Przypadkowo podłączyłem filtr wp_get_nav_menu_itemszamiast wp_nav_menu_objects. Nadal mam problemy z filtrowaniem, jednak są to prawdopodobnie logiczne błędy.

EDYCJA: rozwiążę mój problem, łącząc navbar poziom 2 i navbar poziom 3+ w jeden i oddzielając je css

oto obecna część 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;
}
nonsensation
źródło
Na pierwszy rzut oka wygląda mi dobrze. Czy masz problemy z tym kodem? Sidenote: Możesz skrócić swoje pierwsze zdanie:$echo = ! isset( $args['echo'] ) ?: $args['echo'];
kaiser
1

Wydaje mi się, że możesz sobie z tym poradzić za pomocą CSS, ponieważ domyślnie możesz ukryć opcje menu niższego poziomu, a następnie zdecydować się je pokazać , jeśli mają pewne klasy nad nimi.

Na tej stronie Kodeksu możesz zobaczyć klasy menu (i na swojej stronie). Tak więc dla „drugiego poziomu”, który opisałeś, zakładając, że menu pierwszego poziomu to poziom 1 - a nie 0.

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

A potem coś podobnego do następnego poziomu w dół:

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

Oczywiście zamień „blok” na „blok wbudowany” lub cokolwiek, na co zwykle ustawione są menu.

Być może będziesz musiał się pobawić, aby znaleźć odpowiednią kombinację klas, ale wcześniej miałem szczęście z tą metodą. WP upuszcza tam mnóstwo klas, równie dobrze może z nich korzystać.

Amanda Giles
źródło
Dzięki, użyję niektórych klas w css dla moich pasków nawigacyjnych! :)
nonsensation
Jeśli skorzystałeś z tego rozwiązania, czy możesz zaznaczyć moją odpowiedź jako zaakceptowaną? Dziękuję Ci.
Amanda Giles