Как получить ID элемента в функции start_lvl в Custom Walker для WordPress
Я создаю свой первый кастомный 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";
}

Мне пришлось сделать это в одной из своих тем... Поскольку у вас нет доступа к переменной $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;
}
}

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

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

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

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

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

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

Вы можете использовать следующий фильтр в вашей функции start_el
и получить ваш аргумент в функции start_lvl
.
apply_filters( 'walker_nav_menu_start_lvl', $item_output, $item, $depth, $args->myarg=$item->title );
Пожалуйста, дайте мне знать, если это сработает.

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

Вы можете просто добавить $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'а красным.

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

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

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

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

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

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

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

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