wp_nav_menu () 필터


9

내 탐색을 3 개의 단일 탐색 모음 (레벨 1, 레벨 2 및 레벨 3+)으로 분할하려고합니다. 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)입니다. 세 번째 탐색 표시 줄 (레벨 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

3
이에 대한 답변은 맞춤형 워커 클래스와 관련이 있습니다. 아마도 이것은 잠재적 인 답변자에게 도움이 될 것입니다.
Tom J Nowell

감사합니다. 나는 이번 주말에만 php / wp를 파고 들었으므로 익숙하지는 않습니다. 사용자 지정 Walker를 시도했지만 Walker는 한 번에 하나의 단일 항목 만 처리하므로 현재 항목과 비교할 수 없습니다. 그리고 필터는 내 맞춤 인수를 허용하지 않습니다. 흠 ...
무감각

답변:


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 이상을 하나로 결합하고 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

1

기본적으로 하위 레벨 메뉴 옵션을 숨기고 특정 클래스가있는 경우 표시 하도록 선택할 수 있다는 점에서 CSS를 통해이를 처리 할 수있는 것 같습니다 .

이 코덱스 페이지 , 메뉴 클래스를 참조하십시오 (당신의 페이지 자체에서) 할 수 있습니다. 따라서 첫 번째 레벨 메뉴가 0이 아니라 레벨 1이라고 가정 한 "두 번째 레벨"에 대해 설명합니다.

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의 클래스를 사용할 것입니다! :)
nonsensation

이 솔루션을 사용하게 된 경우 내 답변을 수락 된 것으로 표시 할 수 있습니까? 감사합니다.
Amanda Giles
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.