过滤wp_nav_menu()


9

我尝试将导航分为3个单个导航栏(1、2、3+级)。三是因为它们在网站上是分开的,因此只能根据当前页面显示。

-0-------1--------2-------3+- level/depth
Home
 |
 |\___ Lobby
 |
 |\___ Projects
 |       |\___ Project A
 |       |       |\___ Review
 |       |       |\___ Comments
 |       |       \____ Download
 |       \____ Project B
 |               |\___ Review
 |               |\___ Comments
 |               \____ Download
 |\___ Blog
 |
 \____ About
         |\___ Legal
         \____ Contact

包含级别1的第一个导航栏始终可见。仅当im当前在相应的父页面上时,第二个导航栏(级别2)。第三个导航栏也是如此(级别3+,另外,因为该导航栏还将包含级别3的子页面和子子页面...)。

简而言之:我想在其导航栏中显示所有父菜单,并且仅显示当前页面的直接子菜单。

我试过的

function my_nav_menu( $args = array() )
{
    $echo = isset( $args['echo'] ) ? (bool)( $args['echo'] ) : true;
    $args['echo'] = false;

    add_filter( 'wp_get_nav_menu_items' , 'my_nav_menu_filter' , 666 , 3 );

    $menu = wp_nav_menu( $args );

    remove_filter( 'wp_nav_menu_objects' , 'my_nav_menu_filter' , 666 );

    if( $echo )
        echo $menu;
    else
        return $menu;
}

function my_nav_menu_filter( $items , $menu , $args )
{
    //var_dump( $args );

    $navLevel = isset( $args['navlevel'] ) ? (int)( $args['navlevel'] ) : 0;

    //echo 'navlevel = ' . $args['navlevel'] . ' | ' . $navLevel;

    if( $navLevel == 1 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
                unset( $items[$key] );
        }
    }
    else if( $navLevel == 2 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
            {
                $page = get_page( $item->menu_item_parent );

                if( $page->menu_item_parent == 0 )
                    continue;
            }

            unset( $items[$key] );
        }
    }
    else if( $navLevel == 3 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
            {
                $page = get_page( $item->menu_item_parent );

                if( $page->menu_item_parent != 0 )
                    continue;
            }

            unset( $items[$key] );
        }
    }
    else
    {
        //var_dump( $items );
    }

    return $items;
}

在我的header.php中调用它: <?php my_nav_menu( array( 'echo' => false , 'navlevel' => 1 ) ); ?>

但是$args设置为默认值,并且我的自定义条目未navlevel显示在过滤器中。

如何按照说明拆分导航栏?如何设置自定义$args条目?


2
美好的一天,欢迎来到WPSE。我必须祝贺你第一次提出史诗般的构造性问题。清晰明确的结构良好的问题总是会吸引很多注意力,而且答案也很好。+1
Pieter Goosen 2014年

3
答案涉及定制的Walker课,也许这对任何潜在的答题者都有帮助
Tom J Nowell

谢谢。我只在这个周末才开始研究php / wp,所以我不是这个熟悉的人。我尝试了一个自定义的Walker,但是Walker一次只能处理一个项目,因此无法将其与当前项目进行比较。过滤器不接受我的自定义参数。嗯...
不动声色

Answers:


3

我想我得到了答案:

function my_nav_menu( $args = array() )
{
    $echo = isset( $args['echo'] ) ? (bool)( $args['echo'] ) : true;

    $args['echo'] = false;

    add_filter( 'wp_nav_menu_objects' , 'my_filter_nav_menu' , 100 , 2 );

    $menu = wp_nav_menu( $args );

    remove_filter( 'wp_nav_menu_objects' , 'my_filter_nav_menu' , 100, 2 );

    if( $echo )
        echo $menu;
    else
        return $menu;
}

这可以解决问题:让我更改菜单项,并且自定义参数仍然可用。我不小心将过滤器插入wp_get_nav_menu_items而不是wp_nav_menu_objects。我仍然在过滤方面遇到问题,但是这些可能是一些逻辑错误。

编辑:我将通过将导航栏级别2和导航栏级别3+合并为一个并将其与CSS分开来解决我的问题

继承人当前的PHP部分:

function serthy_filter_nav_menu( $items , $args )
{
    $argArray = (array)( $args );

    if( isset( $argArray['toplevel'] ) )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
                unset( $items[$key] );
        }

        return $items;
    }

    global $post;

    $arr = array();

    foreach( $items as $key => $item )
    {
        $parentIDs = get_post_ancestors( $item->ID );

        foreach( $parentIDs as $i => $parentID )
        {
            if( $parentID == $post->ID )
            {
                array_push( $arr , $item );

                break;
            }
        }
    }

    return $arr;
}

乍一看对我来说很好。您是否对该代码有疑问?旁注:您可以缩短您的第一条声明:$echo = ! isset( $args['echo'] ) ?: $args['echo'];
kaiser 2014年

1

在我看来,您可以通过CSS来处理此问题,因为您可以默认隐藏下级菜单选项,然后选择显示它们上方是否具有某些类的菜单项。

此Codex页面上,您可以看到菜单类(以及页面本身)。因此,对于您描述的“第二级”,假设第一级菜单为1级-而不是0。

ul > li > ul.sub-menu { display: none; }  /* Hide by default */
ul > li.current-menu-parent > ul.sub-menu { display: block; } /* Show menu */

然后再进行下一个类似的操作:

ul > li > ul.sub-menu > li > ul.sub-menu{ display: none; }  /* Hide by default */
ul > li > ul.sub-menu > li.current-menu-parent > ul.sub-menu { display: block; }

显然用“ inline-block”或通常设置为菜单的任何内容替换“ block”。

您可能需要四处寻找合适的类组合,但是我以前对这种方法很幸运。WP在那里放了很多类,不妨使用它们。


谢谢,我将在CSS中使用一些类来导航栏!:)
不动声色

如果您最终使用了此解决方案,能否将我的回答标记为已接受?谢谢。
Amanda Giles 2014年
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.