Добавить родительский элемент меню в подменю в custom nav_walker

Вопрос или проблема

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

Того, чего я пытаюсь достичь, это:

 <ul class="menu">
   <li>
     <a href="https://wordpress.stackexchange.com/questions/318600/linktomenu">Элемент уровня 0</a>
     <ul class="submenu">
       <li><a href="linktoparent">Показать все элементы уровня 0 </a></li>
       <li><a href="#0">Вернуться к родителю</a></li>
       <li><a href="https://wordpress.stackexchange.com/questions/318600/linktomenu">Элемент уровня 1</a></li>
       <li><a href="https://wordpress.stackexchange.com/questions/318600/linktomenu">Элемент уровня 1</a></li>
     </ul>
   </li>
 </ul>

Это код, который у меня есть в данный момент

 <?php

class mobilenav_walker_nav_menu extends Walker_Nav_Menu {

  private $color_idx = 0;

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

    $back_btn = '';

    if($display_depth > 0){
      $parent_label="<li class="go-back"><a href="#0"><span class="parent_label"></span><i class="fa fa-close"></i></a></li>";

      $back_btn = '<li class="see-all"><a class="hit-area" href="#">Назад</a><i class="fa fa-chevron-left"></i></li>';
    }

    // создание html
    $incri = $this->color_idx-1;
    $output .= "\n" . $indent . '<ul class="menu__level" data-menu="submenu-'.$incri.'">' .$parent_label.$back_btn. "\n";
  }

  // добавление основных/подклассов к элементам li и ссылкам
  function start_el( &$output, $item, $depth = 0, $args = Array(), $id = 0 ) {

    global $wp_query;
    $indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // отступ кода

    // классы, зависящие от уровня
    $depth_classes = array(
        'sidebar-item',
        ( $depth == 0 ? 'li0' : '' ),
        ( $depth == 1 ? 'li1' : '' ),
        ( $depth == 2 ? 'li2' : '' ),
        ( $depth == 3 ? 'li3' : '' ),
        ( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
        'menu-item-depth-' . $depth
    );

    if(in_array('menu-item-has-children',$item->classes)){
      $has_children = 'data-has-children="1"';
      $has_children_var = 1;
      $depth_classes[] = 'has-children';
    } else{
      $has_children_var = 0;
      $depth_classes[] = 'no-children';
    }

    $li_attributes="data-level="".$depth.'" data-title="'.apply_filters( 'the_title', $item->title, $item->ID ).'" '.$has_children;

    $depth_class_names = esc_attr( implode( ' ', $depth_classes ) );

    // переданные классы
    $classes = empty( $item->classes ) ? array() : (array) $item->classes;
    $class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );

    // создание html
    $output .= $indent . '<li class="menu__item"'.$li_attributes.'>';

    // атрибуты ссылки
    $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
    $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
    $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
    if($has_children_var == 1){
      $attributes .= ' data-submenu="submenu-'.$this->color_idx.'"';
    }
    $attributes .= ' class="menu__link"';

    $item_output = sprintf( '%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s',
      $args->before,
      $attributes,
      $args->link_before,
      apply_filters( 'the_title', $item->title, $item->ID ),
      ($has_children_var == 1 ? $args->link_after : ''),
      $args->after
    );

    // создание html
    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

    if($has_children_var == 1){
      $this->color_idx++;
    }
  }
}

Это текущий вывод, который у меня есть

  <ul id="menu-hoofdnavigatie" class="sidebar-menu level-0">
    <li class="menu__item" data-level="0" data-title="Пункт меню уровня 0" data-has-children="1"><a data-submenu="submenu-0" class="menu__link">Пункт меню уровня 0</a>
      <ul class="menu__level" data-menu="submenu-0">
        <li class="go-back"><a href="#0"><span class="parent_label"></span><i class="fa fa-close"></i></a></li>
        <li class="see-all"><a class="hit-area" href="#">Назад</a><i class="fa fa-chevron-left"></i></li>
        <li class="menu__item" data-level="1" data-title="Пункт меню 1 уровня 1"><a class="menu__link">Пункт меню 1 уровня 1</a></li>
        <li class="menu__item" data-level="1" data-title="Пункт меню 2 уровня 1"><a class="menu__link">Пункт меню 2 уровня 1</a></li>
        <li class="menu__item" data-level="1" data-title="Пункт меню 3 уровня 1"><a class="menu__link">Пункт меню 3 уровня 1</a></li>
        <li class="menu__item" data-level="1" data-title="Пункт меню 4 уровня 1"><a class="menu__link">Пункт меню 4 уровня 1</a></li>
        <li class="menu__item" data-level="1" data-title="Пункт меню 5 уровня 1"><a class="menu__link">Пункт меню 5 уровня 1</a></li>
      </ul>
    </li>
  </ul>

Я довольно нов в WordPress navwalker, можете помочь мне с этим? Я обыскал весь интернет, но пока не нашел решения моей проблемы.

Итак, вам нужен реальное имя и URL родителя в подменю.

У вас нет информации о пункте поста в вашей function start_lvl().

Но в function start_el() у вас есть элементы и возможно запросить его родителя.

Это требует некоторого рефакторинга с переносом строк, таких как if($display_depth > 0){ условие из start_lvl функции в вашу start_el функцию. Затем написание подходящего WP запроса для получения информации о родительском элементе, необходимой в подменю.

Чуть более конкретный совет:

В функции start_el у вас есть переменная $item, которая должна содержать ID поста, который она представляет. Должно быть $itemId = $item->Id.
Если это так, вы должны получить родителя с $parentId = wp_get_post_parent_id( $itemId ); и, более того, вы можете получить информацию о родительском элементе с ID родителя с другими WP функциями.

Надеюсь, это поможет вам найти ваш путь…

Ответ или решение

Для добавления родительского элемента в подменю при кастомной навигации в WordPress с использованием класса nav_walker, необходимо произвести значительные изменения в текущем коде, чтобы обеспечить корректное отображение названия и URL родительского элемента в подменю. Давайте подробным образом разберем, как этого можно достичь.

Теория

WordPress использует систему навигационных меню для упрощения управления и отображения меню на сайте. Для кастомизации этой системы часто применяются классы, такие как Walker_Nav_Menu, которые позволяют изменять структуру и оформление HTML-кода, генерируемого WordPress. Walker_Nav_Menu предоставляет методы для лавирования по уровням меню – start_lvl и start_el. Ваша задача заключается в том, чтобы переместить и расширить логику управления уровнями меню из функции start_lvl в функцию start_el, поскольку именно в start_el у вас есть доступ ко всей информации о каждом элементе меню, включая его родителя.

Пример

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

С другой стороны, метод start_el, отвечающий за формирование HTML кода каждого элемента меню, имеет доступ к объекту $item, который позволяет определить основную информацию, такую как ID, заголовок и родительский элемент. Эти данные можно использовать для извлечения необходимой информации о родительском элементе при формировании подменю.

Применение

  1. Перенос Логики в start_el: Перенесите часть логики из start_lvl в start_el. В частности, необходимо определить ID родительского элемента и его название.

  2. Извлечение Родительского Элемента:

    • Используйте $parentId = wp_get_post_parent_id($item->ID); чтобы получить ID родительского элемента.
    • Используйте get_post или подобные функции для получения информации об этом элементе.
  3. Добавление Родительского Элемента в Подменю:

    • После извлечения информации о родительском элементе, добавьте соответствующую запись в подменю. Например, создайте новый элемент <li> с ссылкой и названием родительского элемента.
  4. Изменение HTML Разметки:

    • При формировании HTML для подменю добавьте полученный элемент. Это можно сделать с помощью конкатенации строк или использования sprintf для более элегантного результата.

Пример кода с учетом предложенного подхода может выглядеть следующим образом:

function start_el(&$output, $item, $depth = 0, $args = [], $id = 0) {
    // Ваша предыдущая логика здесь...

    if ($depth > 0) {
        $parent_id = wp_get_post_parent_id($item->ID);
        if ($parent_id) {
            $parent_post = get_post($parent_id);
            $parent_title = apply_filters('the_title', $parent_post->post_title, $parent_post->ID);
            $parent_link = get_permalink($parent_id);
            $output .= sprintf(
                '<li><a href="%s">Все из %s</a></li>',
                esc_url($parent_link),
                esc_html($parent_title)
            );
        }
    }

    // Остальная часть логики...
}

Заключение

Данный подход требует глубокого понимания механизмов работы WordPress с меню и умелого использования фильтров и функций API для извлечения необходимой информации. Путем рефакторинга и расширения функциональности класса Walker_Nav_Menu вы сможете достичь необходимого результата – добавление ссылки на родительский элемент в подменю. Это не только улучшит пользовательский интерфейс, но и добавит дополнительную навигационную ценность для пользователей, работающих с вашими мобильными меню.

Оцените материал
Добавить комментарий

Капча загружается...