フィルターwp_nav_menu()


9

ナビゲーションを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)は、対応する親ページに現在いる場合のみ。同じことが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エントリを設定するにはどうすればよいですか?


2
こんにちは、WPSEへようこそ。私は最初のタイマーのための壮大な構成された質問であなたを祝福しなければなりません。明確でよく構成された質問は常に良い答えで多くの注目を集めます。+1
ピーターグーセン2014

3
これに対する答えは、カスタムウォーカークラスに関係します。おそらくこれは、潜在的な回答者を助けるでしょう
トムJノーウェル

ありがとうございました。私は今週末だけphp / wpを掘り下げたので、これはなじみのないものです。カスタムウォーカーを試しましたが、ウォーカーは一度に1つのアイテムしか処理しないため、現在のアイテムと比較できません。そして、フィルターは私のカスタム引数を受け入れません。
うーん

回答:


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。まだフィルタリングに問題がありますが、これらはおそらくいくつかの論理的なバグです。

編集:私はnavbarレベル2とnavbarレベル3+を1つに組み合わせ、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'];
カイザー

1

CSSを使用してこれを処理できるので、デフォルトで下位レベルのメニューオプションを非表示にして、その上に特定のクラスがある場合は表示するように選択できます。

、このコーデックスページは、メニューのクラス(とあなたのページ自体に)を参照してくださいすることができます。したがって、説明した「第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はそこに大量のクラスをドロップし、それらを使用することもできます。


おかげで、ナビゲーションバーにcssのクラスをいくつか使用します。:)
感覚の欠如14

このソリューションを使用してしまった場合は、私の回答を承認済みとしてマークしてもらえますか?ありがとうございました。
アマンダジャイルズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.