Как получить ID элемента в функции start_lvl в Custom Walker для WordPress

16 авг. 2012 г., 22:57:02
Просмотры: 18.1K
Голосов: 21

Я создаю свой первый кастомный Walker для построения аккордеонного меню. В качестве основы я использовал этот пример: http://bitacre.com/2025/custom-nav-menu-walker-for-wordpress-themes

Есть две функции. Первая - start_lvl, а затем start_el.

В start_el ID элемента доступен через $item->ID. Кто-нибудь знает, как я могу получить его также в start_lvl? Мне нужно задать ID для <ul> (который окружает подуровни навигации), чтобы я мог управлять его сворачиванием в аккордеонном меню.

Я пытаюсь сгенерировать что-то вроде этого:

<a href="#collapse2">Заголовок 2</a>
<ul id="collapse2">Подменю 2</ul>
<a href="#collapse3">Заголовок 3</a>
<ul id="collapse3">Подменю 3</ul>

Мой код для функции start_lvl:

// добавляем id и классы к ul подменю
function start_lvl( &$output, $depth, $item ) {
    // классы, зависящие от глубины
    $indent = ( $depth > 0  ? str_repeat( "\t", $depth ) : '' ); // отступ кода
    $display_depth = ( $depth + 1); // потому что первый подуровень считается как 0
    $pgid = ; // Как получить ID здесь??
    $classes = array(
        'sub-menu',
        ( $display_depth == 1  ? 'accordion-body collapse' : '' ),
        ( $display_depth % 2  ? 'menu-odd' : 'menu-even' ),
        ( $display_depth >=2 ? 'sub-sub-menu' : '' ),
        'menu-depth-' . $display_depth
        );
    $ids = array(
        'collapse' . $pgid
        );
    $class_names = implode( ' ', $classes );
    $id_name = implode( ' ', $ids );

    // формируем html
    $output .= "\n" . $indent . '<ul id="' . $id_name . '" class="' . $class_names . '">' . "\n";
}
0
Все ответы на вопрос 3
7
52

Мне пришлось сделать это в одной из своих тем... Поскольку у вас нет доступа к переменной $item на этом этапе Walker, вам нужно сохранить текущий элемент в более глобальной области видимости в тот момент, когда у вас есть доступ к нему. Следующий код прояснит ситуацию... примечание: я оставил только релевантный код.

class ThemeTruck_Nav_Walker extends Walker_Nav_Menu {
   private $curItem;

  // получаем текущий элемент
  function start_lvl(&$output, $depth = 0, $args = array()) {
    var_dump($this->curItem );
  }

  // сохраняем текущий элемент
  function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
    $this->curItem = $item;
  }

 }
3 янв. 2013 г. 07:34:27
Комментарии

Это самое элегантное решение в данной ветке обсуждения. Спасибо, Lane!

Kevin C. Kevin C.
1 июн. 2013 г. 01:05:44

Действительно очень чистый подход, который отлично работает. Большое спасибо.

Isaac Gregson Isaac Gregson
1 июн. 2015 г. 20:08:13

Не уверен, но нужно ли добавлять весь стандартный код в start_el, чтобы это заработало?

GDY GDY
7 февр. 2017 г. 09:27:55

Хорошо, вы можете просто использовать parent::start_el($output,$item,$depth,$args,$id); в start_el ...

GDY GDY
7 февр. 2017 г. 09:37:40

Блестяще, давно хотел разобраться с этим, и это сработало сразу. Спасибо.

cfx cfx
21 июн. 2018 г. 04:55:47

Отлично!! У меня очень большое меню нужно построить, и ваше решение просто вау. Спасибо!

Jankyz Jankyz
17 янв. 2020 г. 16:35:38

Спустя годы это меня спасло! Спасибо :)

Paxjah Paxjah
5 февр. 2024 г. 21:00:33
Показать остальные 2 комментариев
2

Вы можете использовать следующий фильтр в вашей функции start_el и получить ваш аргумент в функции start_lvl.

apply_filters( 'walker_nav_menu_start_lvl', $item_output, $item, $depth, $args->myarg=$item->title );

Пожалуйста, дайте мне знать, если это сработает.

16 сент. 2012 г. 12:43:17
Комментарии

Спасибо за публикацию! Надеюсь найти время разобраться в ближайшие дни, но сейчас я очень занят учебой. Я сообщу вам о результате!

Robert Bouten Robert Bouten
17 сент. 2012 г. 23:09:14

Не уверен, существовал ли этот фильтр раньше, но в WP 5.5 такого фильтра, насколько я вижу, нет

Alexander Holsgrove Alexander Holsgrove
28 окт. 2020 г. 21:11:13
11
-1

Вы можете просто добавить $page в аргументы пользовательского walker'а:

class My_Custom_Walker extends Walker_page {
    function start_el(&$output, $page, $depth, $args, $current_page) {
        if ( $depth )
            $indent = str_repeat("\t", $depth);
        else
            $indent = '';

        extract($args, EXTR_SKIP);

        $output .= $indent . 
            '<li>
            <a style="color:red" href="' . get_page_link($page->ID) . '" title="' . 
            esc_attr( wp_strip_all_tags( apply_filters( 'the_title', $page->post_title, $page->ID ) ) ) . '">' . 
            $link_before . apply_filters( 'the_title', $page->post_title, $page->ID ) . $link_after . '</a>';

Попробуйте приведенный выше код, а затем перед вызовом wp_list_pages() добавьте класс пользовательского walker'а:

$MyWalker = new My_Custom_Walker();

Затем, в аргументах для wp_list_pages:

wp_list_pages('walker' => $MyWalker)

Проверьте, стал ли вывод walker'а красным.

16 авг. 2012 г. 23:29:00
Комментарии

Это в функции start_el, но, по-видимому, в start_lvl всё по-другому, потому что я не могу использовать там те же переменные. Или, по крайней мере, не в том же порядке.

Robert Bouten Robert Bouten
16 авг. 2012 г. 23:38:57

Что ты пытаешься сделать с start_lvl?

AlxVallejo AlxVallejo
16 авг. 2012 г. 23:40:45

Я пытаюсь задать для <ul> id="collapse102", где 102 — это сгенерированный ID страницы. Таким образом я смогу управлять его сворачиванием в моём аккордеон-меню.

Robert Bouten Robert Bouten
16 авг. 2012 г. 23:50:50

Добавление id="collapse" работает, но у меня не получается добавить также pageID.

Robert Bouten Robert Bouten
16 авг. 2012 г. 23:51:58

Вы имеете в виду, что хотите сворачивать только определенные ID? У меня есть аккордеонное дерево для wp_list_pages, и мне вообще не нужно изменять start_lvl.

AlxVallejo AlxVallejo
16 авг. 2012 г. 23:54:56

Я добавил пример того, что пытаюсь сгенерировать

Robert Bouten Robert Bouten
16 авг. 2012 г. 23:59:43

Это для wp_nav_menu, не знаю, имеет ли это значение для wp_list_pages

Robert Bouten Robert Bouten
17 авг. 2012 г. 00:00:45

Привет AlxVallejo, у меня не получается заставить это работать так, как я думал, поэтому мне придется изменить подход. Как ты сделал свой аккордеон для wp_list_pages?

Robert Bouten Robert Bouten
20 авг. 2012 г. 18:14:06

@RobertBouten Я обновил свой ответ. На самом деле я использую плагин под названием list-pages-shortcode, чтобы не приходилось вызывать класс в каждом шаблоне страницы. Дай мне знать, как у тебя получится.

AlxVallejo AlxVallejo
20 авг. 2012 г. 18:59:22

@RobertBouten Я понимаю, что это не даст вам 100% аккордеона, что будет зависеть от используемого jQuery. Скорее всего, вам нужно будет назначить каждой ссылке класс, который будет вызываться из DOM jQuery. Буду рад показать, как я это реализовал.

AlxVallejo AlxVallejo
20 авг. 2012 г. 19:42:23

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

Robert Bouten Robert Bouten
21 авг. 2012 г. 23:34:28
Показать остальные 6 комментариев