Как стилизовать текущий пункт меню при использовании Walker в WordPress
Я создал пользовательское меню и хочу стилизовать отдельные элементы li в зависимости от того, является ли пункт текущей страницей или нет? Обычно это делается просто с помощью класса типа current-menu-item. Однако я также использую Walker в своей навигации для отображения дополнительного поля описания - это, похоже, отключает стандартные классы. Может кто-нибудь помочь?
<div id="navigation">
<?php
$walker = new My_Walker;
wp_nav_menu(array( 'menu' => 'nav','walker' => $walker ) );
?>
</div><!-- END navigation -->
ОБНОВЛЕНИЕ:
class My_Walker extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth, $args) {
global $wp_query;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
$class_names = '';
$output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';
$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;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
$item_output .= '<span>' . $item->description . '</span>';
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
Поздний ответ, но решил внести свой вклад, так как эта страница была в топе Google при поиске решения данной проблемы. Я тоже упустил из виду тот факт, что WordPress по умолчанию добавляет текущий пункт меню (спасибо patnz за указание на это).
Однако мне не нравится, насколько раздута разметка при использовании стандартных классов, поэтому для тех, кому это интересно, можно использовать строку кода, подобную следующей:
$class_names = in_array("current_page_item",$item->classes) ? ' active' : '';
Для полноты картины — вот как это будет выглядеть в вашем примере кода:
class My_Walker extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth, $args) {
global $wp_query;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = in_array("current_page_item",$item->classes) ? ' active' : '';
$output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';
$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;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
$item_output .= '<span>' . $item->description . '</span>';
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}

Очень позднее дополнение, но если вы используете архив пользовательского типа записи в качестве пункта меню, вам нужно изменить проверку in_array
на "current-menu-item"
. Если сделать это, функция по-прежнему будет работать на отдельных страницах или записях.
Не знаю, изменилось ли это с момента написания ответа 10 лет назад, поэтому мое решение, возможно, было недоступно в то время.

Вы сбрасываете стандартные классы, поэтому они не добавляются.
// этот код очищает классы, которые должны быть добавлены
$class_names = '';
Попробуйте так:
class My_Walker extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth, $args) {
global $wp_query;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
$class_names = ' class="' . esc_attr( $class_names ) . '"';
$output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';
$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;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
$item_output .= '<span>' . $item->description . '</span>';
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
