web-dev-qa-db-ja.com

Wp_nav_menu()をフィルタリング

ナビゲーションを3つの単一ナビゲーションバー(レベル1、レベル2、レベル3 +)に分割します。 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を含む最初のナビゲーションバーは常に表示されています。 2番目のナビゲーションバー(レベル2)は、imが現在対応する親ページにある場合のみです。同じことが3番目のナビゲーションバー(レベル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-エントリを設定する方法

9
nonsensation

私は答えを得たと思います:

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

これはトリックをします:私はmenuitemsを変えさせます、そして、カスタム引数はまだ利用可能です。誤ってフィルタをwp_get_nav_menu_itemsではなくwp_nav_menu_objectsにフックしました。私はまだフィルタリングに関して問題を抱えています、しかしこれらはおそらくいくつかの論理的なバグです..

編集:私は1つにナビゲーションバーのレベル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;
}
3
nonsensation

デフォルトでは下位レベルのメニューオプションを hide にして、それより上に特定のクラスがある場合は show にすることができます。

このコーデックスページ で、メニュークラスを見ることができます(そしてあなたのページ自体で)。だから、あなたが説明した「第2レベル」では、第1レベルのメニューはレベル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; }

明らかに "block"を "inline-block"あるいはあなたのメニューが通常設定されているものに置き換えてください。

あなたはクラスの正しい組み合わせを見つけるために試してみる必要があるかもしれませんが、私は前にこの方法でうまくいっています。 WPはそこにたくさんのクラスをドロップします、それらを使うかもしれません。

1
Amanda Giles