問題描述

我嘗試尋找有關如何從自定義選單中排除/刪除導航選單項的資訊,而我發現唯一的 thread 沒有任何對我有用的答案。

背景:

我在我的網站上使用 WP 自定義選單 (wp_nav_menu) 和 jqDock 組合了一個 Dock 選單。由於 jqDock 需要連續的影像或影像連結才能發揮作用,所以我使用自定義步行器,因此導航選單 HTML 輸出看起來像這樣:

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

我的自定義步行者的程式碼是:

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="'%20%20%20.%20esc_attr(%20$item->url%20%20%20%20%20%20%20%20)%20.'"' : '';

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

}

然後,jqDock 指令碼捕獲選單 ID(‘menu-first’),並使用 Dock 選單替換 wp_nav_menu 輸出。 Dock 選單的 HTML 輸出根據載入 jqDock 時指定的選項而更改。

問題:

我不想根據使用者在網站上的位置顯示 (即排除) 某些選單項。例如,當使用者不在家中時,我只想顯示 「家庭」 專案,只有當他在時,才顯示 「隨機」 郵件專案。

丟棄的解決方案:

一個。多種選單:註冊和建立多個選單,然後有條件地呼叫它們可以工作; 不過,由於很多原因,我認為這不是理想的,也不是一個乾淨的解決方案。此外,多個選單不容易維護或更新。

灣正規表示式搜尋和替換:這可能會迫使我每次更改 jqDock 選項時更改針引數,因為 HTML 輸出被修改。

C 。 CSS ‘display’ 屬性:透過 CSS 顯示屬性隱藏專案的作用,但由於它必須應用於 jqDock 選單輸出,它會影響選單的視覺化渲染。

4. 解決方案失敗

一個。過濾到 wp_nav_menu_items:我嘗試捕獲’$items’ 變數 (字串),並透過條件標記為以下程式碼分配不同的值:

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

這隻能部分工作,因為選單項確實改變,但條件標籤被忽略。我想這是有道理的,因為應用過濾器的時刻。

灣自定義導航選單功能:我嘗試建立自己的自定義導航選單功能,以便可以向 $ defaults 陣列新增一個 exclude 引數,並使用 wp_list_pages 中稍作修改的程式碼填充附加引數:

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

有任何想法嗎?

最佳解決方案

方法 1

您可以向自定義沃克新增一個建構函式來儲存一些其他的排除引數,如:

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

或者放下建構函式並設定其 $exclude 屬性,然後將其作為步行者傳遞給 wp_nav_menu(),如下所示:

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

根據您排除的內容,將正確的表單提供給排除。

方法 2

這是透過掛入 wp_get_nav_menu_items 過濾器來做到這一點。

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

注意:object_id 是選單指向的物件,而 ID 是選單 ID,這些都不同。

讓我知道你的想法。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。