Filter wp_nav_menu ()


9

Ich versuche meine Navigation in 3 einzelne Navigationsleisten aufzuteilen (Level 1, Level 2 und Level 3 +). Drei, weil sie über die Site getrennt sind und nur abhängig von der aktuellen Seite angezeigt werden sollten.

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

Die erste Navigationsleiste mit der Ebene 1 ist immer sichtbar. Die zweite Navigationsleiste (Stufe 2) nur, wenn ich gerade auf der entsprechenden übergeordneten Seite bin. Gleiches gilt für die dritte Navigationsleiste (Stufe 3+, plus, da diese Navigationsleiste auch Unterseiten und Unterseiten ... der Stufe 3 enthält).

Kurz gesagt: Ich möchte alle übergeordneten Menüs in ihren Navigationsleisten und nur die direkten untergeordneten Menüs der aktuellen Seite anzeigen.

Was ich versucht habe:

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

Aufruf in meiner header.php: <?php my_nav_menu( array( 'echo' => false , 'navlevel' => 1 ) ); ?>

Wird jedoch $argsauf die Standardwerte gesetzt und mein benutzerdefinierter Eintrag navlevelwird nicht im Filter angezeigt.

Wie kann ich meine Navigationsleiste wie beschrieben teilen? Wie $argsstelle ich meinen benutzerdefinierten Eintrag ein?


2
Guten Tag und willkommen bei WPSE. Ich muss Ihnen zu einer episch konstruierten Frage für einen ersten Timer gratulieren. Gut konstruierte Fragen, die klar sind, erhalten mit guten Antworten immer viel Aufmerksamkeit. +1
Pieter Goosen

3
Die Antwort darauf beinhaltet eine benutzerdefinierte Walker-Klasse. Vielleicht hilft dies potenziellen Antwortenden
Tom J Nowell

Danke. Ich habe mich erst an diesem Wochenende mit PHP / WP beschäftigt, also bin ich nicht so vertraut. Ich habe einen benutzerdefinierten Walker ausprobiert, aber der Walker verarbeitet jeweils nur einen einzelnen Artikel, sodass ich ihn nicht mit dem aktuellen Artikel vergleichen kann. Und ein Filter akzeptiert mein benutzerdefiniertes Argument nicht. Hmmm ...
Nonsensation

Antworten:


3

Ich glaube ich habe die Antwort bekommen:

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

Dies macht den Trick: Lassen Sie mich die Menüs ändern und benutzerdefinierte Argumente sind noch verfügbar. Ich habe versehentlich den Filter eingehängt wp_get_nav_menu_itemsanstatt wp_nav_menu_objects. Ich habe immer noch Probleme mit der Filterung, aber dies sind wahrscheinlich einige logische Fehler.

BEARBEITEN: Ich werde mein Problem lösen, indem ich Navbar Level 2 und Navbar Level 3+ zu einem kombiniere und sie mit CSS trenne

Hier ist der aktuelle PHP-Teil:

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

Sieht für mich auf den ersten Blick gut aus. Haben Sie Probleme mit diesem Code? Nebenbemerkung: Sie können Ihre erste Aussage verkürzen:$echo = ! isset( $args['echo'] ) ?: $args['echo'];
Kaiser

1

Es scheint mir , dass Sie dies durch CSS in umgehen konnte , dass man konnte verstecken die untere Ebene Menüoptionen standardmäßig und dann entscheiden, zeigen sie , wenn sie über ihnen bestimmte Klassen haben.

Auf dieser Codex-Seite sehen Sie die Menüklassen (und auf Ihrer Seite selbst). Angenommen, das Menü der ersten Ebene ist für die von Ihnen beschriebene "zweite Ebene" Ebene 1 - nicht 0.

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

Und dann etwas Ähnliches für das nächste Level:

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

Ersetzen Sie "Block" offensichtlich durch "Inline-Block" oder was auch immer Ihre Menüs normalerweise eingestellt sind.

Möglicherweise müssen Sie herumspielen, um die richtige Kombination von Klassen zu finden, aber ich hatte zuvor viel Glück mit dieser Methode. WP lässt dort eine Menge Klassen fallen, könnte sie genauso gut verwenden.


Danke, ich werde einige Klassen in CSS für meine Navigationsleisten verwenden! :)
Nonsensation

Wenn Sie diese Lösung verwendet haben, können Sie meine Antwort bitte als akzeptiert markieren. Danke.
Amanda Giles
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.