从wp_nav_menu动态排除菜单项


17

我尝试查找有关如何从自定义菜单中排除/删除导航菜单项的信息,而我发现的唯一线程没有任何对我有用的答案。

1.背景:

我在网站上使用WP自定义菜单(wp_nav_menu)和jqDock组合了一个Dock菜单。由于jqDock需要连续的图像或图像链接来发挥其魔力,因此我使用了自定义的Walker,因此导航菜单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="'   . 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 .= "";
    }

}

然后,jqDock脚本捕获菜单ID(“菜单优先”),并将wp_nav_menu输出替换为Dock菜单。Dock菜单的HTML输出根据加载jqDock时指定的选项而变化。

2.问题:

我不想根据用户在网站上的位置显示(即排除)某些菜单项。例如,我只想在用户不在主页中时显示主页项,而在用户不在时显示随机帖子项。

3.废弃的解决方案:

一种。多个菜单:注册并创建多个菜单,然后有条件地调用它们是可行的;但是,出于多种原因,我认为这既不是理想的解决方案也不是干净的解决方案。另外,多个菜单也不容易维护或更新。

b。正则表达式搜索和替换:由于HTML输出已修改,因此每次更改jqDock选项时,这可能迫使我更改needle参数。

C。CSS'display '属性:通过CSS display属性隐藏项目是可行的,但是由于必须将其应用于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');

这仅部分起作用,因为菜单项确实发生了变化,但是条件标签被忽略了。我认为这是有道理的,因为应用了滤镜的那一刻。

b。自定义导航菜单功能:我尝试创建自己的自定义导航菜单功能,以便能够向$ defaults数组中添加一个exclude参数,并使用此经过稍微修改的代码wp_list_pages填充其他参数:

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

有任何想法吗?


您可以向我们展示您的自定义学步儿童班吗?
soulseekah

嗨,Souleseekah,我只是将其添加到了我的原始帖子中。谢谢!
Marventus

我也想传递一个exclude参数,但是wp_list_pages与许多其他WP函数相反,wp_nav_menu它不包含一个参数。因此,即使我在调用菜单时或在助行器中确实指定了一个菜单,也不会在菜单中找到wp_nav_menu它,对吗?
Marventus

抱歉,我写这封信时没想好,马上删除了。
soulseekah

不用担心!
Marventus 2011年

Answers:


26

方法1

您可以将构造函数添加到自定义Walker中,以存储一些其他排除参数,例如:

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属性,然后再将其作为walker传递给它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是菜单ID,但它们是不同的。

让我知道你的想法。


谢谢!那可能行得通。我会尝试的,让您知道。
Marventus

我尝试了构造方法,无论如何尝试,该in_array函数始终收到“第二个参数的数据类型错误”错误。难道我做错了什么?
Marventus

$exclude属性必须是一个数组。因此,请确保将数组传递给构造函数,或者在我的答案中观看更新的代码。特别是针对的类型转换$this->exclude,以防万一未通过数组的情况。
soulseekah

抱歉:我的功能有错字。我只是尝试$exclude = array ('4', '7');并使用了子弹,但是它对助步器的输出没有任何影响。我将尝试第二种方法,并让您知道。
Marventus 2011年

不,那也不起作用。我想我
无法解决

0

这有帮助吗

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

举个例子

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

嗨,萨克(Saq),我忘了提到一个行不通的解决方案是创建一个自定义nav_menu函数,并将该代码添加为该函数默认值的附加参数。可悲的是,它没有用。我没有尝试将其包含在walker中,但是由于上面提到的相同原因,我认为这也不起作用,主要是因为wp_nav_menu没有“排除”参数,但是我可能是错的。
Marventus 2011年

为了清楚起见,我更新了原始帖子以包含此内容。
Marventus 2011年

如果你不使用自定义学步车,而不是使用常规的nav_menu,并与您的自定义图像中提取与wp_get_nav_menu_items项目()
SAQ

通常,这是一个很好的解决方法,但是在这种特定情况下,wp_get_nav_menu_items由于img标签未存储在实际的自定义菜单中(仅它们的文件名位于描述字段中,例如“ image1.png” ,因此不会检索图像) )。自定义的walker允许我在菜单输出中插入img标签。
Marventus,2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.