Schließen Sie Menüelemente dynamisch aus wp_nav_menu aus

17

Ich habe nach Informationen zum Ausschließen / Entfernen von Navigationsmenüelementen aus benutzerdefinierten Menüs gesucht. Der einzige Thread, den ich gefunden habe, enthielt keine für mich nützlichen Antworten.

1. Hintergrund:

Ich habe ein Dock-Menü mit benutzerdefinierten WP-Menüs (wp_nav_menu) und jqDock auf meiner Site zusammengestellt. Da jqDock fortlaufende Bilder oder Bildverknüpfungen benötigt, um seine Magie zu entfalten, benutze ich einen benutzerdefinierten Walker, damit die HTML-Ausgabe des Navigationsmenüs so aussieht:

<div id="menu-first" class="nav">
<a><img src="http://path/to/image-1.png"/></a>
<a><img src="http://path/to/image-2.png"/></a>
<a><img src="http://path/to/image-3.png"/></a>
etc...
</div>

Der Code für meinen benutzerdefinierten Walker lautet:

class custom_nav_walker extends Walker_Nav_Menu 
{
    var $tree_type = array( 'post_type', 'taxonomy', 'custom' );
    var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );

    function start_lvl(&$output, $depth) {
        $indent = str_repeat("\t", $depth);
        $output .= "\n$indent<ul class=\"sub-menu\">\n";
    }

    function end_lvl(&$output, $depth) {
        $indent = str_repeat("\t", $depth);
        $output .= "$indent</ul>\n";
    }

    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        ) .'"' : '';

        $description  = ! empty( $item->description ) ? esc_attr( strtolower( $item->description )) : '';
        $item_title   = ! empty( $item->attr_title )  ? esc_attr( $item->attr_title ) : '';

        if ( strpos($description, ';') !== false ) {
        $description_array = explode (';', $description);
            $image_name = $description_array[0];
            $image_alt = $description_array[1];
        } else {
            $image_name = $description;
            $image_alt = $item_title;
        }

        $item_output = $args->before;
        $item_output .= '<a'. $attributes .'>';
        $item_output .= $args->link_before .'<img src="'.get_bloginfo('template_url').'/images/skin1/'.$image_name.'" alt="'.$image_alt.'" title="'.$item_title.'" />'.$args->link_after;
        $item_output .= '</a>';
        $item_output .= $args->after;

        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }

    function end_el(&$output, $item, $depth) {
        $output .= "";
    }

}

Das jqDock-Skript erkennt dann die Menü-ID ('menu-first') und ersetzt die Ausgabe von wp_nav_menu durch die Ausgabe des Dock-Menüs. Die HTML-Ausgabe des Dock-Menüs ändert sich basierend auf den Optionen, die beim Laden von jqDock angegeben wurden.

2. Die Frage:

Ich möchte bestimmte Menüpunkte nicht anzeigen (dh ausschließen), je nachdem, wo sich der Benutzer auf der Site befindet. Zum Beispiel möchte ich das Basiselement nur anzeigen, wenn sich der Benutzer nicht in der Basis befindet, und das Element "Zufälliger Beitrag" nur, wenn er sich in der Basis befindet.

3. Weggeworfene Lösungen:

ein. Mehrfachmenüs: Das Registrieren und Erstellen mehrerer Menüs und das anschließende Aufrufen unter bestimmten Bedingungen können funktionieren. Ich denke jedoch, dass dies aus vielen Gründen überhaupt keine ideale oder saubere Lösung ist. Außerdem sind mehrere Menüs nicht einfach zu warten oder zu aktualisieren.

b. Regex Suchen und Ersetzen: Das kann mich zwingen , das zu ändern Nadel ich die jqDock Optionen Parameter jedes Mal ändern , da die HTML - Ausgabe geändert wird.

c. CSS-Eigenschaft 'display': Das Ausblenden der Elemente über die CSS-Anzeigeeigenschaft funktioniert. Da sie jedoch auf die Ausgabe des jqDock-Menüs angewendet werden muss, wirkt sie sich auf die visuelle Darstellung des Menüs aus.

4. Fehlgeschlagene Lösungen:

ein. Nach wp_nav_menu_items filtern : Ich habe versucht, die Variable '$ items' (Zeichenfolge) abzufangen und ihr verschiedene Werte über bedingte Tags mit folgendem Code zuzuweisen :

function userf_dynamic_nav_menu ($items) {
    $items_array_home = explode('<a', $items);
    $items_array_nothome = $items_array_home;

    unset($items_array_home[1]);
    unset($items_array_nothome[2]);

    $items_home = implode('<a', $items_array_home);
    $items_nothome = implode('<a', $items_array_nothome);

    if ( is_home() ) {
        $items = $items_home;
    } else {
        $items = $items_nothome;
    }
    return $items;
}
add_filter('wp_nav_menu_first_items', 'userf_dynamic_nav_menu');

Dies funktioniert nur teilweise, da sich die Menüelemente zwar ändern, die bedingten Tags jedoch ignoriert werden. Ich denke, dies ist sinnvoll, da der Filter in dem Moment angewendet wird.

b. Benutzerdefinierte Navigationsmenüfunktion : Ich habe versucht, eine eigene benutzerdefinierte Navigationsmenüfunktion zu erstellen, um dem Array $ defaults ein Ausschlussargument hinzuzufügen und diesen leicht geänderten Code von wp_list_pageszu verwenden, um das zusätzliche Argument auszufüllen:

$exclude_array = ( $args->exclude ) ? explode(',', $args->exclude) : array();
$args->exclude = implode( ',', apply_filters('wp_nav_menu_excludes', $exclude_array) );

Irgendwelche Ideen?

Marventus
quelle
Können Sie uns Ihren individuellen Kinderlaufkurs zeigen?
Soulseekah
Hallo Souleseekah, ich habe es gerade zu meinem ursprünglichen Beitrag hinzugefügt. Vielen Dank!
Marventus
Ich dachte auch daran, ein excludeArgument zu übergeben, aber im Gegensatz zu wp_list_pagesvielen anderen WP-Funktionen wp_nav_menuenthält es keines. Selbst wenn ich beim Aufrufen des Menüs oder im Walker eines angeben würde wp_nav_menu, würde es doch nicht von innen aufgenommen werden , oder?
Marventus
Tut mir leid, ich habe nicht klar darüber nachgedacht, als ich das geschrieben habe. Es wurde sofort gelöscht.
Soulseekah
Mach dir keine Sorgen!
Marventus

Antworten:

26

Methode 1

Sie können Ihrem benutzerdefinierten Walker einen Konstruktor hinzufügen, um einige zusätzliche Ausschlussargumente zu speichern, z.

class custom_nav_walker extends Walker_Nav_Menu {
    function __construct( $exclude = null ) {
        $this->exclude = $exclude;
    }

    function skip( $item ) {
        return in_array($item->ID, (array)$this->exclude);
        // or
        return in_array($item->title, (array)$this->exclude);
        // etc.
    }

    // ...inside start_el, end_el
    if ( $this->skip( $item ) ) return;
}

Oder löschen Sie den Konstruktor, und legen Sie seine $excludeEigenschaft fest, bevor Sie ihn als Walker übergeben wp_nav_menu():

$my_custom_nav_walker = new custom_nav_walker;
$my_custom_nav_walker->exclude = array( ... );

Geben Sie, je nachdem, durch was Sie ausschließen, das richtige Formular für den Ausschluss an.

Methode 2

So würden Sie vorgehen, indem Sie sich in den wp_get_nav_menu_itemsFilter einhängen .

function wpse31748_exclude_menu_items( $items, $menu, $args ) {
    // Iterate over the items to search and destroy
    foreach ( $items as $key => $item ) {
        if ( $item->object_id == 168 ) unset( $items[$key] );
    }

    return $items;
}

add_filter( 'wp_get_nav_menu_items', 'wpse31748_exclude_menu_items', null, 3 );

Hinweis: object_idIst das Objekt, auf das das Menü zeigt, und IDist die Menü-ID unterschiedlich?

Lass mich wissen was du denkst.

Soulseekah
quelle
Vielen Dank! Das könnte funktionieren. Ich werde es versuchen und dich wissen lassen.
Marventus
Ich habe den Konstruktor-Ansatz ausprobiert und unabhängig davon, was ich versuche, erhalte ich immer wieder den Fehler "Falscher Datentyp für zweites Argument" für die in_arrayFunktion. Mache ich etwas falsch?
Marventus
Die $excludeEigenschaft muss ein Array sein. Stellen Sie also sicher, dass Sie ein Array an den Konstruktor übergeben, oder sehen Sie sich den aktualisierten Code in meiner Antwort an. Speziell die Typumwandlung für den $this->excludeFall, dass ein Array nicht übergeben wird.
Soulseekah
Entschuldigung: Ich hatte einen Tippfehler in meiner Funktion. Ich habe gerade versucht $exclude = array ('4', '7');, die Schnecken auch zu verwenden, aber es hat keine Auswirkungen auf die Ausgabe des Laufwagens. Ich werde den zweiten Ansatz versuchen und Sie wissen lassen.
Marventus
Nein, das hat auch nicht funktioniert. Ich glaube, ich bin hirntot, weil ich versucht habe, das herauszufinden. Das könnte meine ... "Leistung" beeinträchtigen :-)
Marventus
0

Hilft das

$exclude_array = ( $args->exclude ) ? explode(',', $args->exclude) : array();
$args->exclude = implode( ',', apply_filters('wp_nav_menu_excludes', $exclude_array) );

als Beispiel

< ?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary', 'exclude' => '66' ) ); ?>
saq
quelle
Hallo Saq, ich habe vergessen zu erwähnen, dass eine der Lösungen, die nicht funktionierten, darin bestand, eine benutzerdefinierte Funktion nav_menu zu erstellen und diesen Code als zusätzliches Argument zu den Standardeinstellungen der Funktion hinzuzufügen. Leider hat es nicht funktioniert. Ich habe nicht versucht, es in den Walker aufzunehmen, aber ich glaube nicht, dass dies auch aus dem gleichen Grund funktionieren würde, den ich oben erwähnt habe, hauptsächlich, dass das wp_nav_menuArgument "ausschließen" nicht vorhanden ist, aber ich könnte mich irren.
Marventus
Ich habe meinen ursprünglichen Beitrag aus Gründen der Übersichtlichkeit aktualisiert.
Marventus
Was ist, wenn Sie keinen benutzerdefinierten Walker verwenden, sondern stattdessen ein reguläres nav_menu verwenden und die Elemente mit wp_get_nav_menu_items () mit Ihrem benutzerdefinierten Image
extrahieren
Dies ist im Allgemeinen eine gute Lösung, in diesem speziellen Fall wp_get_nav_menu_itemswerden die Bilder jedoch nicht abgerufen, da die img-Tags nicht im eigentlichen benutzerdefinierten Menü gespeichert sind (nur ihre Dateinamen befinden sich im Beschreibungsfeld, z. B. "image1.png". ). Mit dem benutzerdefinierten Walker kann ich die img-Tags in die Menüausgabe einfügen.
Marventus