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.