Dinamicamente escludere le voci di menu da wp_nav_menu


17

Ho provato a cercare informazioni su come escludere i / nav rimuovere le voci di menu dal menu personalizzati, e l'unico infilare ho trovato non ha avuto alcuna risposta che sono stati utili a me.

1. Contesto:

Ho messo insieme un menu Dock utilizzando i menu personalizzati (WP) e wp_nav_menu jqDock sul mio sito. Dal momento che jqDock ha bisogno di immagini o link immagine continua a lavorare la sua magia, ho' utilizzando una consuetudine walker così l'aspetto di uscita del menu HTML nav dovrebbe occupare in questo modo:

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

Il codice per la mia abitudine walker è:

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 .= "";
    }

}

Lo script jqDock poi cattura l'ID del menu ( 'menù-prima') e sostituisce l'uscita wp_nav_menu con il menu del Dock. cambiamenti di output HTML del menu Dock in base alle opzioni specificate durante il caricamento jqDock.

2. La domanda:

Vorrei non visualizzare (ovvero escludere) determinate voci di menu in base alla posizione dell'utente sul sito. Ad esempio, vorrei mostrare l'elemento Home solo quando l'utente non è nella Home e l'elemento Post casuale solo quando lo è.

3. Soluzioni scartate:

un. Menu multipli: la registrazione e la creazione di più menu e quindi la loro chiamata condizionale potrebbe funzionare; tuttavia, non credo che questa sia una soluzione ideale né pulita per molte ragioni. Inoltre, non è facile mantenere o aggiornare più menu.

b. Cerca e sostituisci Regex: questo potrebbe costringermi a cambiare il parametro dell'ago ogni volta che cambio le opzioni di jqDock perché l'output HTML viene modificato.

c. Proprietà 'display' CSS: nascondere gli elementi attraverso la proprietà di visualizzazione CSS funziona, ma poiché deve essere applicato all'output del menu jqDock, influisce sul rendering visivo del menu.

4. Soluzioni fallite:

un. Filtro su wp_nav_menu_items : ho provato a catturare la variabile '$ items' (stringa) e assegnandogli valori diversi tramite tag condizionali con il seguente codice:

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');

Funziona solo parzialmente, perché le voci di menu cambiano, ma i tag condizionali vengono ignorati. Immagino che questo abbia senso a causa del momento in cui viene applicato il filtro.

b. Funzione di menu di navigazione personalizzata : ho provato a creare la mia funzione di menu di navigazione personalizzata per poter aggiungere un argomento exclude all'array $ defaults e utilizzare questo codice leggermente modificato wp_list_pagesper popolare l'argomento aggiuntivo:

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

Qualche idea?


Puoi mostrarci la tua classe per bambini walker personalizzata?
soulseekah,

Ciao Souleseekah, l'ho appena aggiunto al mio post originale. Grazie!
Marventus,

Ho pensato di passare anche un excludeargomento, ma, contrariamente a wp_list_pagesmolte altre funzioni del WP, wp_nav_menunon ne include una. Quindi, anche se ne specifico uno quando chiamo il menu o nel walker, non verrebbe rilevato all'interno wp_nav_menu, vero?
Marventus,

Mi dispiace, non ho pensato bene quando l'ho scritto, cancellato immediatamente.
soulseekah,

Non ti preoccupare!
Marventus,

Risposte:


26

Metodo 1

È possibile aggiungere un costruttore al Walker personalizzato per memorizzare alcuni argomenti di esclusione aggiuntivi, come:

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

Oppure lascia cadere il costruttore e imposta la sua $excludeproprietà prima di passarlo come walker per fare wp_nav_menu()così:

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

A seconda di cosa stai escludendo, fornisci il modulo corretto per l'esclusione.

Metodo 2

Questo è il modo in cui lo faresti agganciandoti al wp_get_nav_menu_itemsfiltro.

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

Nota: object_idè l'oggetto a cui punta il menu, mentre IDè l'ID del menu, questi sono diversi.

Fatemi sapere i vostri pensieri.


Grazie! Potrebbe funzionare. Ci proverò e ti farò sapere.
Marventus,

Ho provato l'approccio constuctor e, indipendentemente da ciò che provo, continuo a ricevere un errore "Tipo di dati errato per il secondo argomento" per la in_arrayfunzione. Sto facendo qualcosa di sbagliato?
Marventus,

La $excludeproprietà deve essere un array. Quindi assicurati di passare un array nel costruttore o guarda il codice aggiornato nella mia risposta. In particolare il typecast per $this->exclude, nel caso in cui un array non venga passato.
soulseekah,

Scusatemi: avevo un refuso nella mia funzione. Ho appena provato ad $exclude = array ('4', '7');usare anche le lumache, ma non sta avendo effetti sull'output del walker. Proverò il secondo approccio e ti farò sapere.
Marventus,

No, neanche quello ha funzionato. Penso di essere morto di mente nel tentativo di capirlo, quindi ciò potrebbe influenzare la mia ... "esibizione", :-)
Marventus,

0

questo aiuta

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

come esempio

< ?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary', 'exclude' => '66' ) ); ?>

Ciao Saq, ho dimenticato di menzionare che una delle soluzioni che non ha funzionato è stata quella di creare una funzione nav_menu personalizzata e aggiungere quel codice come argomento aggiuntivo ai valori predefiniti della funzione. Purtroppo, non ha funzionato. Non ho provato a includerlo nel walker, ma non penso che funzionerebbe nemmeno per lo stesso motivo che ho menzionato sopra, principalmente che wp_nav_menunon ha un argomento "escluso", ma potrei sbagliarmi.
Marventus,

Ho aggiornato il mio post originale per includerlo per chiarezza.
Marventus,

cosa succede se non usi un walker personalizzato, invece usi un normale nav_menu ed estrai gli elementi con wp_get_nav_menu_items () con la tua immagine personalizzata
saq

Sarebbe una buona soluzione in generale, ma in questo caso particolare wp_get_nav_menu_itemsnon recupererà le immagini perché i tag img non sono memorizzati nel menu personalizzato effettivo (solo i loro nomi di file si trovano nel campo della descrizione, ad esempio "image1.png" ). Il walker personalizzato è ciò che mi consente di inserire i tag img nell'output del menu.
Marventus,
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.