Показ только одного уровня дочерних страниц, проблема с wp_list_pages

24 окт. 2011 г., 17:05:36
Просмотры: 25.1K
Голосов: 5

Я работаю над сайтом, который имеет довольно большую структуру страниц в несколько уровней глубины - в некоторых разделах много страниц.

Базовая структура выглядит примерно так...

Родитель
Родитель
Родитель
-Ребенок
-Ребенок
--Внук
--Внук
--Внук
---Правнук
-Ребенок
-Ребенок
--Внук
--Внук
--Внук
---Правнук
-Ребенок
Родитель
-Ребенок
Родитель
Родитель
-Ребенок
-Ребенок
--Внук
---Правнук
--Внук

Вы понимаете картину - представьте еще больше страниц!

Мое обычное решение с подменю обычно работает нормально (взято прямо из Codex), потому что я работаю с гораздо меньшими сайтами. На этом сайте получается огромное длинное меню, которое слишком велико, чтобы быть полезным.

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

Какую бы комбинацию wp_list_pages я ни пробовал, я мог получить только все или ничего.

Также, поскольку есть разделы без дочерних элементов, нужно показывать ссылки верхнего уровня, когда дочерних элементов нет.

Надеюсь, это имеет смысл - я весь день ломаю голову над этим! Буду благодарен за любую помощь!

РЕДАКТИРОВАНИЕ

Хорошо, добавлю здесь. Извините за мою неопытность!

Огромное спасибо @chip-bennet за то, что довел меня до этого момента!

Теперь у меня есть код, который делает почти все, что мне нужно.

$output = wp_list_pages('echo=0&depth=1&title_li=Sections' );

        if (is_page( )) {

          $page = $post->ID;

          if ($post->post_parent) {
            $page = $post->post_parent;
          }

          $children=wp_list_pages( 'echo=0&child_of=' . $page . '&title_li=' );


          if ($children) {
            $output = wp_list_pages( array(
                // Только страницы, которые являются дочерними для текущей страницы
                'child_of' => $post->ID,
                // Показывать только один уровень иерархии
                'depth' => 1,
                'title_li' => 'В этом разделе'
            ) );
          }


        } 

        echo $output;

Это работает именно так, как я хочу, пока не дойду до конца дерева, когда он ничего не выводит.

Chip дал мне код снова для показа соседних страниц вместо поиска дочерних элементов - однако из-за моего недостатка навыков PHP я испытываю трудности с добавлением его в этот код.

0
Все ответы на вопрос 4
9

Это должно работать, используя только доступные параметры массива аргументов для wp_list_pages(): конкретно, depth и child_of.

Для отображения одного уровня иерархии для дочерних страниц текущей страницы:

<?php
// Глобализируем переменную $post;
// скорее всего, она уже доступна в этом контексте, но на всякий случай...
global $post;
wp_list_pages( array(
    // Только страницы, которые являются дочерними для текущей страницы
    'child_of' => $post->ID,
    // Показывать только один уровень иерархии
    'depth' => 1
) );
?>

Нет необходимости прибегать к пользовательскому классу walker.

РЕДАКТИРОВАНИЕ

Чтобы также отображать ссылки верхнего уровня, просто измените пару параметров:

<?php
// Глобализируем переменную $post;
// скорее всего, она уже доступна в этом контексте, но на всякий случай...
global $post;
wp_list_pages( array(
    // Только страницы, которые являются дочерними для родителя текущей страницы
    'child_of' => $post->post_parent,
    // Показывать два уровня иерархии
    'depth' => 2
) );
?>

Обратите внимание на изменение 'child_of' => $post->ID на 'child_of' => $post->post_parent, что включит страницы родителя текущей страницы, и изменение 'depth' => 1 на 'depth' => 2, что включит соседние страницы текущей страницы и их дочерние страницы.

РЕДАКТИРОВАНИЕ 2

Вот как бы я обработал добавленный вами код. Сначала я бы использовал правильный массив вместо строки массива. Затем я бы выполнил запрос для контекста/дочерних страниц перед созданием массива аргументов для wp_list_pages(), а затем просто вызвал бы wp_list_pages() один раз:

// Используем родительскую страницу, если она существует, иначе текущую страницу
$child_of_value = ( $post->post_parent ? $post->post_parent : $post->ID );
// Глубина 2, если есть родительская страница, иначе глубина 1
$depth_value = ( $post->post_parent ? 2 : 1 );
// Собираем массив аргументов
$wp_list_pages_args = array( 
    'child_of' => $child_of_value,
    'depth' => $depth_value,
    'title_li' => 'Разделы'
);
// Теперь выводим результат
wp_list_pages( $wp_list_pages_args );

Нам понадобится более сложный код, если вам действительно нужно выводить отдельные списки.

24 окт. 2011 г. 17:28:08
Комментарии

Отлично, это определенно направило меня в нужном направлении!

Комбинируя с другим фрагментом кода, я добился 90% от желаемого функционала...

a_kc a_kc
24 окт. 2011 г. 17:47:32

Так каких 10% вам не хватает? :)

Chip Bennett Chip Bennett
24 окт. 2011 г. 17:50:03

Я сделал так, что когда нет дочерних страниц, выводятся страницы верхнего уровня. Это отлично работает, пока не доходишь до нижней части дерева — тогда сейчас ничего не выводится.

В идеале в таком случае должны выводиться страницы того же уровня (сёстры), или, если это невозможно, родительские страницы.

a_kc a_kc
24 окт. 2011 г. 18:04:43

Смотрите обновленный ответ. :)

Chip Bennett Chip Bennett
24 окт. 2011 г. 18:27:20

Я не могу легко опубликовать код здесь, верно?

По сути, я понимаю, как все это работает! К сожалению, я больше по фронтенду, и мое незнание PHP мешает мне все это собрать вместе!

a_kc a_kc
24 окт. 2011 г. 18:47:45

Что это? Мне нужно добавить это к вашему исходному вопросу? Это рабочий/не рабочий код?

Chip Bennett Chip Bennett
24 окт. 2011 г. 18:50:00

Я обновил пост, чтобы немного прояснить ситуацию — сайт находится в стадии разработки по адресу http://cheshirewestlscb-org-uk.temp.connectedcheshire.org.uk/?page_id=365 (это пример внизу иерархии).

a_kc a_kc
24 окт. 2011 г. 19:11:26

Хорошо, смотрите обновлённый (снова) ответ...

Chip Bennett Chip Bennett
24 окт. 2011 г. 19:23:52

Теперь всё идеально! Сэр, вы джентльмен и учёный! Или как-то иначе по-старинке сказать, что это очень любезно с вашей стороны :D

a_kc a_kc
25 окт. 2011 г. 11:40:38
Показать остальные 4 комментариев
0

Вы можете использовать аргумент depth для контроля количества отображаемых уровней вложенности. Я создал Walker для подменю, который отображает меню, начиная с прямых потомков текущей страницы. Код:

class My_Walker_Submenu extends Walker_Nav_Menu {


  function display_element($element, &$children_elements, $max_depth, $depth = 0, $args, &$output) {

    if (! $element)
      return;

    $itemId = null;

    if ( $depth == 0) {
        if (!isset($args[0]->child_of)){
         return;
        }
      foreach ( $children_elements as $id => $children ) {
        $data = get_post_meta ( $id, '_menu_item_object_id', true );
        if ($data == $args [0]->child_of) {
          $itemId = $id;
          break;
        }
      }
      if ($itemId == null) {
        return;
      }
      unset($args [0]->child_of);

      foreach ( $children_elements [$itemId] as $child ) {
        parent::display_element ( $child, $children_elements, $max_depth, $depth + 1, $args, $output );
      }
      return;

    }
    return parent::display_element ( $element, $children_elements, $max_depth, $depth, $args, $output );
  }

И пример использования (я применяю его в сайдбаре):

echo wp_nav_menu( array(
              'container' => '',
              'theme_location' => 'header-menu',
              'walker' => new My_Walker_Submenu(),
              'child_of' => $page->ID, 
              'depth'   => 2
) );
24 окт. 2011 г. 17:14:30
0

Это проблема, с которой я сталкиваюсь довольно часто. Я считаю, что решения с использованием WP_List_Pages, которые встречаются повсюду, уже немного устарели, учитывая, что WordPress имеет полноценный менеджер меню (Внешний вид → Меню).

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

Таким образом, для ваших нужд вы установите start_depth равным 1, и меню автоматически будет игнорировать элементы навигации верхнего уровня при отображении.

Я назвал плагин WP Nav Plus, потому что он расширяет текущие возможности и параметры wp_nav_menu, добавляя аргумент start_depth для отображения дочерних меню.

Для тех, кто заинтересован, плагин доступен на моем сайте: https://mattkeys.me/products/wp-nav-plus/

19 мая 2013 г. 22:50:42
0

Я создал функцию, которая использует wp_list_pages() для реализации этого. Настройте параметры, и всё готово.

Gist

19 февр. 2017 г. 15:37:58