Dynamicznie wyklucz pozycje menu z menu wp_nav_menu


17

Próbowałem znaleźć informacje o tym, jak wykluczyć / usunąć elementy menu nawigacyjnego z niestandardowych menu, a jedyny znaleziony wątek nie zawierał żadnych przydatnych odpowiedzi.

1. Tło:

Złożyłem menu Docka za pomocą niestandardowych menu WP ( wp_nav_menu ) i jqDock na mojej stronie. Ponieważ jqDock potrzebuje ciągłych obrazów lub linków graficznych do działania swojej magii, używam niestandardowego walkera, aby wyjście HTML menu nawigacji wyglądało mniej więcej tak:

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

Kod mojego niestandardowego chodzika to:

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

}

Następnie skrypt jqDock przechwytuje identyfikator menu („menu-first”) i zastępuje dane wyjściowe wp_nav_menu menu menu Dock. Dane wyjściowe HTML menu Docka zmieniają się w zależności od opcji określonych podczas ładowania jqDock.

2. Pytanie:

Chciałbym nie wyświetlać (tzn. Wykluczać) niektórych pozycji menu w zależności od tego, gdzie użytkownik jest na stronie. Na przykład chciałbym wyświetlać element domowy tylko wtedy, gdy użytkownika nie ma w domu, a element losowy - tylko wtedy, gdy on jest.

3. Odrzucone rozwiązania:

za. Wiele menu: rejestrowanie i tworzenie wielu menu, a następnie wywoływanie ich warunkowo, może działać; nie sądzę jednak, aby było to idealne ani czyste rozwiązanie z wielu powodów. Ponadto wiele menu nie jest łatwych w utrzymaniu lub aktualizacji.

b. Wyszukiwanie i zamiana wyrażenia regularnego : może to zmusić mnie do zmiany parametru igły za każdym razem, gdy zmieniam opcje jqDock, ponieważ dane wyjściowe HTML są modyfikowane.

do. Właściwość „display” CSS: Ukrywanie elementów za pomocą właściwości display CSS działa, ale ponieważ należy ją zastosować do danych wyjściowych menu jqDock, wpływa to na wizualne renderowanie menu.

4. Nieudane rozwiązania:

za. Filtruj do wp_nav_menu_items : Próbowałem złapać zmienną „$ items” (ciąg) i przypisać jej różne wartości za pomocą tagów warunkowych z następującym kodem:

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

Działa to tylko częściowo, ponieważ elementy menu się zmieniają, ale tagi warunkowe są ignorowane. Myślę, że ma to sens ze względu na moment, w którym zastosowano filtr.

b. Niestandardowa funkcja menu nawigacyjnego : Próbowałem utworzyć własną niestandardową funkcję menu nawigacyjnego, aby móc dodać argument wykluczenia do tablicy $ defaults i użyć tego nieco zmodyfikowanego kodu z, wp_list_pagesaby wypełnić dodatkowy argument:

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

Jakieś pomysły?


Czy możesz pokazać nam swoją niestandardową klasę dla dzieci z walkerem?
— soulseekah

Cześć Souleseekah, właśnie dodałem go do mojego oryginalnego postu. Dzięki!
— Marventus

Myślałem też o przekazaniu excludeargumentu, ale w przeciwieństwie do wp_list_pageswielu innych funkcji WP, wp_nav_menunie zawiera żadnej. Więc nawet jeśli wybiorę jeden, gdy dzwonię do menu lub w walkerze, nie zostanie odebrany w środku wp_nav_menu, prawda?
— Marventus

Przepraszam, nie myślałem prosto, kiedy to napisałem, natychmiast usunięte.
— soulseekah

Nie martw się o to!
— Marventus

Odpowiedzi:


26

Metoda 1

Możesz dodać konstruktor do niestandardowego Walkera, aby przechowywać dodatkowe argumenty wykluczające, takie jak:

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

Lub upuść konstruktor i ustaw jego $excludewłaściwość przed przekazaniem go jako walkera, aby wp_nav_menu():

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

W zależności od tego, co wykluczasz, podaj prawidłowy formularz do wykluczenia.

Metoda 2

W ten sposób powinieneś to zrobić, podpinając się do wp_get_nav_menu_itemsfiltra.

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

Uwaga: object_idto obiekt wskazywany przez menu, chociaż IDjest to identyfikator menu, są one różne.

Powiedz mi o czym myślisz.


Dzięki! To może zadziałać. Spróbuję i dam ci znać.
— Marventus

Próbowałem podejścia konstruktora i bez względu na to, co próbuję, ciągle pojawia się błąd in_arrayfunkcji „Nieprawidłowy typ danych dla drugiego argumentu” . czy robię coś źle?
— Marventus

$excludeNieruchomość musi być tablicą. Upewnij się więc, że przekazujesz tablicę do konstruktora lub obejrzyj zaktualizowany kod w mojej odpowiedzi. W szczególności typecast dla $this->exclude, na wypadek gdyby tablica nie została przekazana.
— soulseekah

Przepraszam za to: miałem literówkę w swojej funkcji. Właśnie próbowałem $exclude = array ('4', '7');i używam ślimaków, ale nie ma to żadnego wpływu na wydajność walkera. Spróbuję drugiego podejścia i dam ci znać.
— Marventus

Nie, to też nie działało.
— Wydaje

0

czy to pomaga

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

jako przykład

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

Cześć Saq, zapomniałem wspomnieć, że jednym z rozwiązań, które nie działały, było utworzenie niestandardowej funkcji nav_menu i dodanie tego kodu jako dodatkowego argumentu do wartości domyślnych funkcji. Niestety nie zadziałało. Nie próbowałem włączyć go do walkera, ale nie sądzę, żeby to zadziałało z tego samego powodu, o którym wspomniałem powyżej, głównie dlatego, że wp_nav_menunie ma argumentu „wykluczenia”, ale mogę się mylić.
— Marventus

Zaktualizowałem swój pierwotny post, aby dodać go dla jasności.
— Marventus

co jeśli nie użyjesz niestandardowego chodzika, zamiast tego użyjesz zwykłego menu nav_menu i wyodrębnisz elementy za pomocą wp_get_nav_menu_items () swoim niestandardowym obrazem
— saq

To byłoby ogólnie dobre obejście, ale w tym konkretnym przypadku wp_get_nav_menu_itemsobrazy nie będą pobierane, ponieważ tagi img nie są przechowywane w rzeczywistym niestandardowym menu (tylko ich nazwy plików znajdują się w polu opisu, np. „Image1.png” ). Niestandardowy walker pozwala mi wstawiać tagi img w wynikach menu.
— Marventus
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.