Как показать только подменю используя wp_nav_menu()

19 июн. 2012 г., 11:07:20
Просмотры: 31.6K
Голосов: 4

Я использую этот код для отображения подстраниц пользовательского меню, когда находимся на родительской странице. Но этот код также показывает родительскую страницу на странице без подменю, которую я хотел бы скрыть. По сути, нужно использовать этот код только если мы находимся на странице, у которой есть подстраницы.

class Selective_Walker extends Walker_Nav_Menu
{
    function walk( $elements, $max_depth) {

        $args = array_slice(func_get_args(), 2);
        $output = '';

        if ($max_depth < -1) // неверный параметр
            return $output;

        if (empty($elements)) // нечего обходить
            return $output;

        $id_field = $this->db_fields['id'];
        $parent_field = $this->db_fields['parent'];

        // плоское отображение
        if ( -1 == $max_depth ) {
            $empty_array = array();
            foreach ( $elements as $e )
                $this->display_element( $e, $empty_array, 1, 0, $args, $output );
            return $output;
        }

        /*
         * необходимо отображать в иерархическом порядке
         * разделяем элементы на два массива: элементы верхнего уровня и дочерние элементы
         * children_elements - это двумерный массив, например
         * children_elements[10][] содержит все подэлементы, родителем которых является 10.
         */
        $top_level_elements = array();
        $children_elements  = array();
        foreach ( $elements as $e) {
            if ( 0 == $e->$parent_field )
                $top_level_elements[] = $e;
            else
                $children_elements[ $e->$parent_field ][] = $e;
        }

        /*
         * когда ни один из элементов не является элементом верхнего уровня
         * предполагаем, что первый должен быть корнем подэлементов
         */
        if ( empty($top_level_elements) ) {

            $first = array_slice( $elements, 0, 1 );
            $root = $first[0];

            $top_level_elements = array();
            $children_elements  = array();
            foreach ( $elements as $e) {
                if ( $root->$parent_field == $e->$parent_field )
                    $top_level_elements[] = $e;
                else
                    $children_elements[ $e->$parent_field ][] = $e;
            }
        }

        $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' );  // добавлено continent7
        foreach ( $top_level_elements as $e ){  // изменено continent7
            // спускаемся только по текущему дереву
            $descend_test = array_intersect( $current_element_markers, $e->classes );
            if ( !empty( $descend_test ) ) 
                $this->display_element( $e, $children_elements, 2, 0, $args, $output );
        }

        /*
         * если мы отображаем все уровни, и оставшиеся children_elements не пусты,
         * значит у нас есть orphans, которые следует отобразить в любом случае
         */
         /* удалено continent7
        if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
            $empty_array = array();
            foreach ( $children_elements as $orphans )
                foreach( $orphans as $op )
                    $this->display_element( $op, $empty_array, 1, 0, $args, $output );
         }
        */
         return $output;
    }
}

использование в шаблоне:

wp_nav_menu( 
   array(
       'theme_location'=>'primary', 
       'walker'=>new Selective_Walker() 
   )
);
5
Комментарии

Обязательно ли использовать класс Nav Menu Walker? Или достаточно будет применить wp_list_pages

Stephen Harris Stephen Harris
19 июн. 2012 г. 12:21:35

Также - что если вы находитесь на дочерней странице? Выводить только её дочерние элементы (если они есть)? Или дочерние элементы "корневого" родителя?

Stephen Harris Stephen Harris
19 июн. 2012 г. 12:22:34

Я попробовал использовать wp_list_pages, но он не показывал подчинённые страницы, только если они находились непосредственно в меню "Страницы". В моём пользовательском меню есть записи произвольных типов в качестве выпадающих подстраниц, и они не отображались. Этот код - единственное, что пока сработало...

Nolan Nolan
19 июн. 2012 г. 14:08:48

Мне нужен только корневой родитель дочерних элементов.

Nolan Nolan
19 июн. 2012 г. 14:09:05

Я использовал решение из этого вопроса -> http://wordpress.stackexchange.com/questions/2802/display-a-portion-branch-of-the-menu-tree-using-wp-nav-menu/2809#2809

Оно добавляет фильтр к wp_nav_menu, который позволяет передавать параметр 'submenu'.

gdaniel gdaniel
12 нояб. 2014 г. 19:46:09
Все ответы на вопрос 2
0

Я неоднократно сталкивался с этой проблемой в WordPress. В других CMS, которыми я пользовался, в меню всегда была опция start_depth, что значительно упрощало реализацию вторичного или третичного меню (разделенного меню).

WordPress не включает эту функцию; многие решения в интернете используют wp_list_pages, что полностью игнорирует иерархию менеджера меню.

После проб различных walker'ов и виджетов я наконец решил просто написать собственный плагин с опцией start_depth.

Использовать его можно так:

wp_nav_menu(array('theme_location' => 'primary_navigation', 'start_depth' => 1));

Для всех заинтересованных: плагин доступен бесплатно в репозитории WordPress: https://wordpress.org/plugins/wp-nav-plus/

14 мая 2013 г. 04:25:30
0

Я создал бесплатный плагин, который решает эту проблему!

https://wordpress.org/plugins/wp-nav-menu-extended/

Этот плагин расширяет стандартную функцию wp_nav_menu и добавляет дополнительные параметры:

  • level : (integer) (обязательный для работы плагина) Уровень навигационного меню для отображения. Если не передан параметр child_of, показывает все элементы этого уровня
  • child_of : (string|integer) (опционально) Заголовок или ID пункта меню, прямые потомки которого должны быть показаны

Пример использования:

$defaults = array( 'theme_location' => 'main_menu', 'level' => 2, 'child_of' => 'О нас', );

wp_nav_menu( $defaults );
24 февр. 2015 г. 07:11:12