Отображение конкретного пункта меню из wp_nav_menu по ID

18 мая 2011 г., 04:38:57
Просмотры: 18.7K
Голосов: 3

У меня есть меню wp_nav_menu "Main Menu" следующей структуры:

  • Первый уровень (#menu-item-1)
    • Подпункт
    • Подпункт
  • Первый уровень (#menu-item-2)
    • Подпункт
  • Первый уровень (#menu-item-3)
    • Подпункт A
    • Подпункт B
      • Подпункт a.1
    • Подпункт C

В моем шаблоне мне нужно выводить подпункты меню Main Menu для определенного пункта верхнего уровня, например, для пункта с id menu-item-3, где menu-item-3 является текущим верхним пунктом меню.

Что-то вроде такого: (но чтобы это реально работало)

wp_nav_menu( array('menu' => 'Main Menu', 'menu-item-id' => '3' ));

И это должно возвращать:

  • Подпункт A
  • Подпункт B
    • Подпункт a.1
  • Подпункт C

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

Важно: это не дубликат вопроса "http://wordpress.stackexchange.com/questions/2802/display-a-portion-branch-of-the-menu-tree-using-wp-nav-menu". Хотя на той странице есть несколько похожих ответов, ни один из них не работает должным образом с текущей версией WordPress. Речь идет о показе конкретного подпункта меню и всех его дочерних элементов (с неограниченной вложенностью).

5
Комментарии

возможный дубликат Отображение части/ветви дерева меню с помощью wp_nav_menu()

Jan Fabry Jan Fabry
18 мая 2011 г. 09:17:40

Думаю, вы сможете решить этот вопрос, прочитав ответ на этот вопрос. Если после прочтения вы не смогли решить проблему, пожалуйста, отредактируйте свой вопрос, уточнив, что вы пробовали и что не сработало. (Используйте @Jan при ответе в комментарии, чтобы я получил уведомление)

Jan Fabry Jan Fabry
18 мая 2011 г. 09:19:11

Выглядит отлично! Попробую применить сегодня утром, когда прочитаю эти комментарии, и посмотрю, сработает ли. Спасибо, Ян!

TechRemarker TechRemarker
18 мая 2011 г. 15:48:29

К сожалению, после попыток использовать варианты по указанной ссылке, я не нашел рабочего решения. Первый класс Walker просто выводит все пункты меню, то есть не работает. Третий вариант из списка вроде бы работал, но показывает только верхний уровень меню и один уровень вложенности, тогда как мне нужно отображать все уровни. Пробовал вариант с плагином - тоже не работает, просто показывает все пункты меню. Следующий вариант от Alp показывает боковое меню без верхнего уровня (что хорошо), но не отображает дочерние элементы. И последний вариант на странице вообще не работает. Есть предложения?

TechRemarker TechRemarker
18 мая 2011 г. 17:26:01

@heavymark, ты в итоге нашел решение этой проблемы?

Ian Dunn Ian Dunn
9 июл. 2011 г. 19:19:55
Все ответы на вопрос 3
6

Если я правильно понимаю, что вам нужно, это можно сделать с помощью CSS. Вы вызовете wp_nav_menu как обычно, чтобы сгенерировать все ссылки, но затем скроете все, кроме подменю текущей страницы.

Ваш CSS будет выглядеть примерно так:

#sidebar ul.menu li
{
    display: none;
}

    #sidebar ul.menu li.current-page-parent,
    #sidebar ul.menu li.current-page-parent ul,
    #sidebar ul.menu li.current-page-parent ul.li
    {
        display: block;
    }

Обновление: Вы можете посмотреть пример на http://thataboycreative.com, где я использовал этот подход. Вот соответствующий CSS из того примера:

ul.sub-menu
{
    display: none;
}

    #menu-main-navigation > li.current-menu-item ul.sub-menu,
    #menu-main-navigation > li.current-menu-ancestor ul.sub-menu
    {
        display: block;
    }
18 мая 2011 г. 09:03:02
Комментарии

@Ian Это не работает. Я раньше не видел, чтобы использовался "current-page-parent". Насколько я знаю, WordPress генерирует "current-menu-item" и "current_page_item". Но даже используя их, это не срабатывает и просто скрывает всё меню. Вы успешно применяли такой подход на каком-то сайте, на который можно сослаться?

TechRemarker TechRemarker
18 мая 2011 г. 17:40:11

current-page-parent тоже существует, но, возможно, только в некоторых версиях. WordPress не был очень последовательным в именовании классов. Я отредактирую ответ, чтобы показать пример, где я это делал раньше.

Ian Dunn Ian Dunn
18 мая 2011 г. 18:40:13

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

TechRemarker TechRemarker
19 мая 2011 г. 00:24:52

На самом деле, я не думаю, что это так, потому что WordPress кэширует чтение из базы данных. Поэтому, если вы уже вызывали wp_nav_menu() один раз для вашего основного меню, повторный вызов для вторичной навигации не приведет ко второму запросу к базе данных.

Ian Dunn Ian Dunn
19 мая 2011 г. 03:13:10

@Ian, это хорошее замечание, если предположить, что так оно и работает.

TechRemarker TechRemarker
20 мая 2011 г. 18:08:16

Я бегло просмотрел код вчера и wp_nav_menu() в конечном итоге вызывает get_term(), а тот в свою очередь вызывает wp_cache_add() для термина.

Ian Dunn Ian Dunn
21 мая 2011 г. 00:56:11
Показать остальные 1 комментариев
1

Я создал плагин для этого - убедитесь, что передаете ID как СТРОКУ, а не как число. Пожалуйста, оцените мой плагин - это мой первый плагин! :)

Скачать здесь

8 мар. 2012 г. 22:33:22
Комментарии

Префикс для вашей пользовательской функции - wp_? Это однажды сломается.

fuxia fuxia
2 нояб. 2012 г. 22:54:21
1

Другой способ, который я использовал - это прямое получение записей вместо использования wp_nav_menu. Однако это основано на фактической структуре страниц, а не на меню.

functions.php:

function __construct()
{
    $this->currentPageID    = $this->getCurrentPageID();
    $this->sectionChildren    = $this->getSectionChildren();
}

// Получаем ID текущей страницы
function getCurrentPageID()
{
    $currentPage = $_SERVER['REQUEST_URI'];

    if($currentPage == '/')
        $currentPage = '/home';
    $currentPage = get_page_by_path($currentPage);

    if($currentPage)
        return $currentPage->ID;
    else
        return -1;
}

// Получаем ID раздела
function getSectionID()
{
    global $wpdb;

    $currentSectionID = $wpdb->get_var("
        SELECT post_parent
        FROM ". $wpdb->posts ."
        WHERE ID = ". $this->currentPageID
    );

    if($currentSectionID == 0)
        return $this->currentPageID;
    else
        return $currentSectionID;
}

// Получаем дочерние элементы раздела
function getSectionChildren()
{
    global $wpdb;

    $children = $wpdb->get_results("
        SELECT ID, post_title
        FROM ". $wpdb->posts ."
        WHERE
            post_parent = ". $this->getSectionID() ." AND
            post_type = 'page' AND
            post_status = 'publish'
    ", ARRAY_A);

    return $children;
}

sidebar.php:

<ul id="sub-navigation">
    <?php foreach($dc->sectionChildren as $c) : ?>
        <li <?php if($dc->currentPageID == $c['ID']) echo 'class="active"'; ?>><a href="<?php echo get_permalink($c['ID']); ?>"><?php echo $c['post_title']; ?></a></li>
    <?php endforeach; ?>
</ul>
18 мая 2011 г. 18:52:38
Комментарии

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

TechRemarker TechRemarker
19 мая 2011 г. 00:21:15