Wordpress自定义帖子类型层次结构和菜单突出显示(current_page_parent)

时间:2010-07-17 01:43:36

标签: wordpress menu highlight hierarchical custom-post-type

我创建了一个自定义帖子类型的“投资组合”和带有模板的页面,该模板可检索与该自定义帖子类型匹配的所有帖子。

问题是,当我深入查看实际帖子时,帖子似乎位于主菜单突出显示的“博客”下(将current_page_parent显示为类)

永久链接网址是正确的:www.site.com/portfolio/post-slug

但菜单认为父母是'博客'。

这显然是一个等级问题,但我不知道如何解决它。

6 个答案:

答案 0 :(得分:12)

看来这是核心Wordpress代码的一个问题;除了查看静态页面模板时,生成菜单类的代码会将current_page_parent添加到您的Blog页面。

(已经在http://core.trac.wordpress.org/ticket/13543)进行了讨论。

但是,您可以使用page_css_class过滤器使用一些自定义代码解决此问题。例如,沿着这些行添加一些东西到functions.php(不是100%测试):

function my_page_css_class($css_class, $page) {
    if (get_post_type()=='portfolio' || is_page(57)) {
        if ($page->ID == get_option('page_for_posts')) {
            foreach ($css_class as $k=>$v) {
                if ($v=='current_page_parent') unset($css_class[$k]);
            }
        }
        if ($page->ID==57) {
            $css_class[]='current_page_parent';
        }
    }
    return $css_class;
}
add_filter('page_css_class','my_page_css_class',10,2);

当然,用您的投资组合页面的ID替换57。这会在打印博客页面时删除current_page_parent,并在查看单个投资组合或查看投资组合页面时将current_page_parent添加到您的投资组合页面。

答案 1 :(得分:6)

以下是我之前建议的解决方案的优化/扩展版本,它几乎完全自动化。不再需要额外的CSS或菜单属性。

此版本动态获取自定义帖子类型列表,如果当前帖子类型是自定义帖子类型,则会从所有菜单项中删除“current_page_parent”类。

此外,它会检查每个菜单项,看看它是否适用于页面模板,如“page- {custom_post_type_slug} .php”,如果是,则会添加“current_page_parent”类。

过滤器优先级为1,因为某些主题会替换current_page_parent / etc。类似'active'的类(例如'root'就是这样),所以这个过滤器需要先执行。

最后,它使用了3个静态变量,因为这个函数被重复调用,并且这些(显然)通过所有调用保持不变。

function theme_current_type_nav_class($css_class, $item) {
    static $custom_post_types, $post_type, $filter_func;

    if (empty($custom_post_types))
        $custom_post_types = get_post_types(array('_builtin' => false));

    if (empty($post_type))
        $post_type = get_post_type();

    if ('page' == $item->object && in_array($post_type, $custom_post_types)) {
        if (empty($filter_func))
            $filter_func = create_function('$el', 'return ($el != "current_page_parent");');

        $css_class = array_filter($css_class, $filter_func);

        $template = get_page_template_slug($item->object_id);
        if (!empty($template) && preg_match("/^page(-[^-]+)*-$post_type/", $template) === 1)
            array_push($css_class, 'current_page_parent');

    }

    return $css_class;
}
add_filter('nav_menu_css_class', 'theme_current_type_nav_class', 1, 2);

PS。只是指出我到目前为止看到的所有非CSS解决方案中的一个缺点,包括我自己的: 未考虑的是突出显示链接到显示当前自定义帖子类型的帖子的页面的项目的菜单项父/祖先。考虑一个自定义的帖子类型“产品”和菜单,如:

Home  Company  News  Contact
      |
      \--About Us
      \--Products

“产品”是一个包含模板“page-product.php”的页面,并显示“产品”类型的帖子的概述。由于发布了解决方案,它突出显示。但是,“公司”作为其父/祖先也应该突出显示,但事实并非如此。要记住的事情。

答案 2 :(得分:3)

WP票证:http://core.trac.wordpress.org/ticket/16382

function fix_blog_menu_css_class( $classes, $item ) {
    if ( is_tax( 'my-cat-tax' ) || is_singular( 'my-post-type' ) || is_post_type_archive( 'my-post-type' ) ) {
        if ( $item->object_id == get_option('page_for_posts') ) {
            $key = array_search( 'current_page_parent', $classes );
            if ( false !== $key )
                unset( $classes[ $key ] );
        }
    }

    return $classes;
}
add_filter( 'nav_menu_css_class', 'fix_blog_menu_css_class', 10, 2 );

答案 3 :(得分:0)

我在这方面做了一些更多的研究,并找到了另一种方法。

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;

}

我从这篇文章中获得了一些帮助,然后对其进行了修改,以便从博客页面中删除“current_page_parent”类。 https://wordpress.stackexchange.com/questions/3014/highlighting-wp-nav-menu-ancestor-class-w-o-children-in-nav-structure/3034#3034

亲切 伐由

答案 4 :(得分:0)

这是一个适合我的解决方案,无需在代码中定义我的自定义帖子类型或菜单ID或页面ID:

http://dtbaker.net/web-development/how-to-stop-wordpress-automatically-highlighting-the-blog-page-in-the-menu/

function dtbaker_wp_nav_menu_objects($sorted_menu_items, $args){
    // this is the code from nav-menu-template.php that we want to stop running
    // so we try our best to "reverse" this code wp code in this filter.
    /* if ( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && empty( $wp_query->is_page ) && $home_page_id == $menu_item->object_id )
            $classes[] = 'current_page_parent'; */

    // check if the current page is really a blog post.
    //print_r($wp_query);exit;
    global $wp_query;
    if(!empty($wp_query->queried_object_id)){
        $current_page = get_post($wp_query->queried_object_id);
        if($current_page && $current_page->post_type=='post'){
            //yes!
        }else{
            $current_page = false;
        }
    }else{
        $current_page = false;
    }


    $home_page_id = (int) get_option( 'page_for_posts' );
    foreach($sorted_menu_items as $id => $menu_item){
        if ( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && empty( $wp_query->is_page ) && $home_page_id == $menu_item->object_id ){
            if(!$current_page){
                foreach($sorted_menu_items[$id]->classes as $classid=>$classname){
                    if($classname=='current_page_parent'){
                        unset($sorted_menu_items[$id]->classes[$classid]);
                    }
                }
            }
        }
    }
    return $sorted_menu_items;
}
add_filter('wp_nav_menu_objects','dtbaker_wp_nav_menu_objects',10,2);

答案 5 :(得分:0)

https://core.trac.wordpress.org/ticket/16382 所述,为了向后兼容,select 匹配“任何不是页面的内容”(请记住,这在 10 年前被认为是向后的......)所以现在的主题真的不应该继续使用它。

因此,最简单也是最有效的解决方案(因为与之前的答案不同,它不需要在每次页面加载时运行额外的代码),就是修改主题的 CSS 以将 .current_page_parent 类选择器的使用替换为.current_page_parent,做正确的事。 (注意下划线与连字符。)

如果您使用的是第三方主题并且不想直接修改它,那么您可以在您自己的样式表中覆盖其属性。例如,如果您的主题具有:

.current-menu-parent

然后在您子主题的样式表中,您可以这样做以取消其效果,并将它们应用于正确的类:

.current_page_parent > a {
    border-bottom: 4px solid blue;
}

这只是一个例子 - 正确的方法将取决于您的主题如何设置这些链接的样式。