Differman
@Differman

Как изменить структуру дочернего пункта меню в Wordpress?

Как в Wordpress обернуть пункт меню, имеющий дочерние подпункты в произвольный тег, например, <span>

На примере.

По умолчанию меню Wordpress формируется так:
<nav>									
 <ul >
<li ><a href="#">Пункт меню</a></li>
<li ><a href="#">Пункт меню</a></li>
<li><a href="#">Пункт меню с дочерними пунктами</a>
<ul class="sub-menu">
	<li><a href="#">Дочерний пункт меню</a></li>
</ul>
</li>
</ul>
</nav>


Возможно ли без изменения верстки преобразовать это в нечто следующее:
<nav>
<ul>
<li><a href="#">Пункт меню</a></li>
<li><a href="#">Пункт меню</a></li>
<li>	<span class="opener"><a href="#">Пункт меню с дочерними пунктами</a></span>
<ul>
<li><a href="#">Дочерний пункт меню</a></li>
</ul>
</li>
</ul>
</nav>


Буду признателен, если ответ будет дан для таких двоечников как я, чуть более развернуто.
  • Вопрос задан
  • 1052 просмотра
Решения вопроса 1
AntonLitvinenko
@AntonLitvinenko
HTML coder
Изменение разметки производится путем изменения класса walker_nav_menu
https://misha.agency/wordpress/nav-menu-walkers.html

Готовый код

<?php

class Header_Walker_Nav_Menu extends Walker_Nav_Menu {

	function start_lvl( &$output, $depth = 0, $args = NULL ) {
		$output .= '<ul class="submenu sub-menu">';
	}

	function start_el( &$output, $item, $depth = 0, $args = NULL, $id = 0 ) {
		//global $wp_query;

		$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

		$class_names = $value = '';
		$classes = empty( $item->classes ) ? array() : (array) $item->classes;
		$classes[] = 'menu-item-' . $item->ID;

		if ($args->walker->has_children) {
			$classes[] = 'has-dropdown';
		}

		// функция join превращает массив в строку
		$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
		$class_names = ' class="' . esc_attr( $class_names ) . '"';

		$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
		$id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';

		$output .= $indent . '<li' . $id . $value . $class_names .'>';

		// атрибуты элемента, title="", rel="", target="" и href=""
		$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        ) .'"' : '';
		$attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';

		// ссылка и околоссылочный текст
		$item_output = $args->before;
		if ($args->walker->has_children) {
			$item_output .= '<span class="opener"><a'. $attributes .'>';
		} else {
			$item_output .= '<a'. $attributes .'>';
		}

		$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;

		if ($args->walker->has_children) {
			$item_output .= '</a></span>';
		} else {
			$item_output .= '</a>';
		}

		$item_output .= $args->after;

		$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
	}
}


Для понимания как это работает, берем прямо копируем весь класс walker_nav_menu и там где нужно делаем манипуляции. Конкретно в этом коде добавлен класс submenu к выпадающему меню, добавлен класс has-dropdown к элементу li, внутри которого будет выпадающее меню и завернуты в span с классом opener ссылки, если у родительского li есть выпадающее меню.

В принципе, если вам нужно пункт меню у всех завернуть, то можно поступить следующим образом
<?php
	wp_nav_menu(
		array(
			'theme_location'  => 'main-menu',
			'menu'            => '', 
			'container'       => false, 
			'menu_class'      => 'main-menu', 
			'depth'           => 2,
			'before'          => '<span class="opener">',
			'after'           => '</span>',
			//'walker'          => new Header_Walker_Nav_Menu,
		)
	);
?>

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

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы