(主持人注意:最初的标题为“ wp_nav_menu祖先类,导航结构中没有子类”)

我的标题中有一个wp_nav_menu,其中有三页。当我在这些页面之一上时,菜单中包含该页面的li获得类.current_page_item。这三个页面都有模板,并且这些模板包含自定义查询,以获取特定内容类型的所有帖子。实际上,这个顶层页面的“孩子”实际上并不是孩子,它们只是我使用模板与该顶层页面相关联的一种内容类型。

我希望就像顶层菜单项一样,当用户浏览特定帖子类型的单个页面时,也可以获取'current-ancestor'类,同样,该页面仅在模板文件中的自定义查询中与该页面相关联。

希望很有道理-如果没有,让我知道我在哪里失去了你!非常感谢您的帮助。

-针对特定内容进行了编辑:
例如,我有一个名为Workshops的静态页面,它使用的是模板。它的子弹是车间。该模板具有一个自定义的get_posts函数并在其中循环,从而拉出并显示称为研讨会的自定义内容类型的所有帖子。如果单击这些研讨会的标题之一,那么我将被带到该内容的全部内容。自定义帖子类型的永久链接结构设置为Workshops / postname,因此,正如用户看到的那样,这些内容是Workshops页面的子级,实际上,它们都是一种内容类型,但与页面无关。这是我需要在菜单中有效关闭的空白,当浏览类型为“ workshop”的内容时突出显示“ Workshops”菜单项。

再次,希望这是有道理的,我想我说的是'workshop在一段中超过20次!

评论

@Gavin-您能提供更多您想要完成的事情的细节吗?用具体术语写一个答案比我们尝试抽象地回答要容易得多。另外,如果您可以解释与这些内容相关的URL结构,将很有帮助。

@Gavin-有帮助。因此,您的顶层菜单选项是“ Workshops”中的车间列表,其路径为/ workshops /,并且当用户位于车间页面(即/ workshops / example-workshop /)上时,您希望“ Workshops”菜单项分配了current_page_item类,对吗?

wp_nav_menu()公开当前菜单祖先类

#1 楼

有一个更简单的解决方案。忘记为每种帖子类型创建页面就可以拥有导航项,因为如您所知,WP无法识别正在浏览的自定义类型与该页面相关。

相反,在外观->菜单中创建一个自定义链接。只需输入将返回您的自定义类型的URL并给它一个标签,然后按“添加到菜单”。

http://example.com/workshops/


或非漂亮的永久链接:

http://example.com/?post_type=workshops


这仅会简单地创建一个导航按钮,显示具有该自定义帖子类型的所有帖子,并且在单击该按钮后还会添加当前菜单项类导航项-但除了该URL之外,它不会在其他任何URL上添加导航类

,一旦创建,就进入该新项的配置并输入自定义项在“标题属性”(Title Attribute)字段中输入文章类型(您也可以使用描述字段,但默认情况下该字段在管理屏幕选项中处于隐藏状态)。

现在,您需要钩住nav_menu_css_class过滤器(这会针对每个导航项触发),并检查查看的内容是否属于您的自定义导航项中指示的帖子类型:

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {
    $post_type = get_query_var('post_type');
    if ($item->attr_title != '' && $item->attr_title == $post_type) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}


在这种情况下,我们将检查“标题属性”字段的内容是否不正确为空,并且与当前查询的post_type相匹配。如果是这样,我们将current-menu-item类添加到其类数组中,然后返回修改后的数组。

您可以对其进行修改以仅匹配导航项的标题,但是如果出于某些原因您想使用不同于标题类型的简单标题来命名导航项,使用“标题属性”或“描述”字段可为您提供灵活性。

现在,任何时候您在查看单个项时(或者可能是在查看单个项时)匹配导航菜单项的帖子类型),该项将获得CSS类current-menu-item,以便突出显示。

无需页面或页面模板;-) URL查询负责获取正确的帖子。循环模板负责显示查询输出。此功能负责识别显示的内容并添加CSS类。

BONUS

您甚至可以使用wp_update_nav_menu_item自动执行此过程,方法是为所有您的菜单项自动生成帖子类型。对于此示例,您首先需要检索要将此项目添加到的导航菜单的$menu_id

$types = get_post_types( array( 'exclude_from_search' => false, '_builtin' => false  ), 'objects' );
foreach ($types as $type) {
    wp_update_nav_menu_item( $menu_id, 0, array(
        'menu-item-type' => 'custom',
        'menu-item-title' => $type->labels->name,
        'menu-item-url' => get_bloginfo('url') . '/?post_type=' . $type->rewrite['slug'],
        'menu-item-attr-title' => $type->rewrite['slug'],
        'menu-item-status' => 'publish'
        )
    );
}


评论


那是东西!我之所以使用页面模板,是因为这些页面的布局相当复杂,并且不仅仅列出页面,但是我仍然可以利用您提供的过滤器来检查页面ID。该主题的本质是主题选项使您可以匹配页面(“ home”是此页面,“ about”是此页面,等等),因此应该可以完美地工作。感谢您的帮助(非常详尽)!

–加文
2010-10-19 11:59



我必须从属于我的博客的导航项中删除current_page_parent-否则它可以工作。谢谢

–pkyeck
2011-10-10 14:58

这对我不起作用,因为$ item-> attr_title拔出了TITLE,并且我用大写字母写了该标题。所以我将属性更改为$ item-> post_name,现在对我来说很好用。

–honk31
13年11月29日在17:42

我试图使代码适合我的主题,但无法使其正常工作。当我处于自定义帖子类型投资组合中时,菜单中没有适用于我的父项的类。我已经使用了上面的代码。可能是什么问题?

–凯斯
2014年3月25日15:51

#2 楼

而不是使用


$ post_type =
get_query_var('post_type');


您可能想要尝试:


$ post_type = get_post_type();


有时,在查询var中未设置发布类型。默认的post_type为“ post”就是这种情况,因此,如果要突出显示从列表页面列出的帖子,则需要使用它。对于非自定义的帖子类型,get_very_var()只会返回一个空字符串。

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {
    $post_type = get_post_type();
    if ($item->attr_title != '' && $item->attr_title == $post_type) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}


#3 楼

@Somatic-太棒了!我对您的代码进行了一些修改,因此它也适用于特定的分类法(我仅将其用于相关的post_type)。这个想法是使用菜单项的Title属性来存储post_type的名称和分类法的名称,并用分号分隔,然后使用该函数进行分解。

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {

    # get Query Vars
    $post_type = get_query_var('post_type');  
    $taxonomy = get_query_var('taxonomy');

    # get and parse Title attribute of Menu item
    $title = $item->attr_title; // menu item Title attribute, as post_type;taxonomy
    $title_array = explode(";", $title);
    $title_posttype = $title_array[0];
    $title_taxonomy = $title_array[1];

    # add class if needed
    if ($title != '' && ($title_posttype == $post_type || $title_taxonomy == $taxonomy)) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}


#4 楼

这是我的解决方案,如果您想使用wp_list_pages。

将其添加到函数中。php

add_filter('page_css_class', 'my_page_css_class', 10, 2);
function my_page_css_class($css_class, $page){
    $post_type = get_post_type();
    if($post_type != "page"){
        $parent_page = get_option('page_for_custom_post_type-'.$post_type);
        if($page->ID == $parent_page)
            $css_class[] = 'current_page_parent';
    }
    return $css_class;
}


现在只需在wp_options表中添加一个一个新行,其option_name为page_for_custom_post_type-xxxx,其option_value具有要连接的页面ID。

您可能已经意识到已经有一个名为page_for_posts的选项。如果您只有1种自定义帖子类型,则可以在下拉菜单中的/wp-admin/options-reading.php中设置页面,导航将正确设置current_page。

我认为wordpress核心应该扩展此部分,其中列出了每种注册的帖子类型的下拉列表。

#5 楼

我决定坚持使用页面,并在导航项上使用页面模板名称作为类。这使我避免使我对其他一些解决方案不满意的title属性变得混乱。

add_filter('nav_menu_css_class', 'mbudm_add_page_type_to_menu', 10, 2 );
//If a menu item is a page then add the template name to it as a css class 
function mbudm_add_page_type_to_menu($classes, $item) {
    if($item->object == 'page'){
        $template_name = get_post_meta( $item->object_id, '_wp_page_template', true );
        $new_class =str_replace(".php","",$template_name);
        array_push($classes, $new_class);
        return $classes;
    }   
}


我还将主体类添加到header.php

<body <?php body_class(); ?>>


最后,此解决方案需要一些额外的功能css将选定/活动状态应用于导航菜单项。我用它来显示与该页面相关的分类档案和自定义帖子类型,作为此页面的子代:

/* selected states - include sub pages for anything related to products */
#nav-main li.current-menu-item a,
body.single-mbudm_product #nav-main li.lp_products a,
body.tax-mbudm_product_category #nav-main li.lp_products a,
#nav-main li.current_page_parent a{color:#c00;}


评论


这给了我以下错误:警告:join()[function.join]:在第76行的/home/path/to/wp-includes/nav-menu-template.php中传递了无效的参数。

–杰夫·K。
2011年10月21日,0:04

哦,我想我知道发生了什么事。这是因为您正在if语句中返回$ classs。只需将return $ classs移到外部,之后便可以解决上述错误。

–杰夫·K。
2011年10月21日,1:14



#6 楼

@Somatic-很棒的代码!我自己做了一个改变。我想保留“标题属性”以达到其预期目的,因此我将“自定义帖子类型”子句放置在“链接关系”(XFN)高级菜单属性中,您可以在“屏幕选项”中启用该属性。我修改了

if ($item->attr_title != '' && $item->attr_title == $post_type) {


并将其更改为

if ($item->xfn != '' && $item->xfn == $post_type) {


#7 楼

Somatic不错。

,不幸的是,我不知道如何在页面中以您的解释方式列出自定义帖子类型。如果我不使用page-portfolio.php并将其添加到页面中,那么我得到的只是404页。

如果我像Gavin一样,我对您的功能做了一些修改,像这样从博客页面中删除“ current_page_parent”。

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2);
function current_type_nav_class($css_class, $item) {
$post_type = get_query_var('post_type');

if (get_post_type()=='portfolio') {
    $current_value = "current_page_parent"; 
    $css_class = array_filter($css_class, function ($element) use ($current_value) { return ($element != $current_value); } );
}

if ($item->attr_title != '' && $item->attr_title == $post_type) {       
    array_push($css_class, 'current_page_parent');
};
return $css_class;


}