WordPress. Меню навигации. Часть 2 из 2
25.03.2019
Теги: CMS • Web-разработка • WordPress • Меню • Навигация
Использование параметра walker
Для построения меню WordPress использует класс Walker_Nav_Menu
, объект этого класса является значением по умолчанию для параметра walker
функции wp_nav_menu()
. Мы можем создать свой класс и переопределить в нем методы, чтобы формировать html-код меню, как нам нужно. Например, чтобы задать CSS-класс nav-item
для элементов <li>
и CSS-класс nav-link
для элементов <a>
:
<?php class My_Walker_Nav_Menu extends Walker_Nav_Menu { /** * Starts the element output. * * @since 3.0.0 * @since 4.4.0 The {@see 'nav_menu_item_args'} filter was added. * * @see Walker::start_el() * * @param string $output Used to append additional content (passed by reference). * @param WP_Post $item Menu item data object. * @param int $depth Depth of menu item. Used for padding. * @param stdClass $args An object of wp_nav_menu() arguments. * @param int $id Current item ID. */ public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) { if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) { $t = ''; $n = ''; } else { $t = "\t"; $n = "\n"; } $indent = ( $depth ) ? str_repeat( $t, $depth ) : ''; $classes = empty( $item->classes ) ? array() : (array) $item->classes; $classes[] = 'menu-item-' . $item->ID; // добавляем CSS-класс nav-item для элементов <li> $classes[] = 'nav-item'; // добавляем CSS-класс active для текущей страницы if ($item->current) { $classes[] = 'active'; } /** * Filters the arguments for a single nav menu item. * * @since 4.4.0 * * @param stdClass $args An object of wp_nav_menu() arguments. * @param WP_Post $item Menu item data object. * @param int $depth Depth of menu item. Used for padding. */ $args = apply_filters( 'nav_menu_item_args', $args, $item, $depth ); /** * Filters the CSS class(es) applied to a menu item's list item element. * * @since 3.0.0 * @since 4.1.0 The `$depth` parameter was added. * * @param array $classes The CSS classes that are applied to the menu item's `<li>` element. * @param WP_Post $item The current menu item. * @param stdClass $args An object of wp_nav_menu() arguments. * @param int $depth Depth of menu item. Used for padding. */ $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) ); $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : ''; /** * Filters the ID applied to a menu item's list item element. * * @since 3.0.1 * @since 4.1.0 The `$depth` parameter was added. * * @param string $menu_id The ID that is applied to the menu item's `<li>` element. * @param WP_Post $item The current menu item. * @param stdClass $args An object of wp_nav_menu() arguments. * @param int $depth Depth of menu item. Used for padding. */ $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args, $depth ); $id = $id ? ' id="' . esc_attr( $id ) . '"' : ''; $output .= $indent . '<li' . $id . $class_names .'>'; $atts = array(); $atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : ''; $atts['target'] = ! empty( $item->target ) ? $item->target : ''; $atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : ''; $atts['href'] = ! empty( $item->url ) ? $item->url : ''; /** * Filters the HTML attributes applied to a menu item's anchor element. * * @since 3.6.0 * @since 4.1.0 The `$depth` parameter was added. * * @param array $atts { * The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored. * * @type string $title Title attribute. * @type string $target Target attribute. * @type string $rel The rel attribute. * @type string $href The href attribute. * } * @param WP_Post $item The current menu item. * @param stdClass $args An object of wp_nav_menu() arguments. * @param int $depth Depth of menu item. Used for padding. */ $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth ); // добавляем CSS-класс nav-link для ссылок $atts['class'] = 'nav-link'; $attributes = ''; foreach ( $atts as $attr => $value ) { if ( ! empty( $value ) ) { $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value ); $attributes .= ' ' . $attr . '="' . $value . '"'; } } /** This filter is documented in wp-includes/post-template.php */ $title = apply_filters( 'the_title', $item->title, $item->ID ); /** * Filters a menu item's title. * * @since 4.4.0 * * @param string $title The menu item's title. * @param WP_Post $item The current menu item. * @param stdClass $args An object of wp_nav_menu() arguments. * @param int $depth Depth of menu item. Used for padding. */ $title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth ); $item_output = $args->before; $item_output .= '<a'. $attributes .'>'; $item_output .= $args->link_before . $title . $args->link_after; $item_output .= '</a>'; $item_output .= $args->after; /** * Filters a menu item's starting output. * * The menu item's starting output only includes `$args->before`, the opening `<a>`, * the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is * no filter for modifying the opening and closing `<li>` for a menu item. * * @since 3.0.0 * * @param string $item_output The menu item's starting HTML output. * @param WP_Post $item Menu item data object. * @param int $depth Depth of menu item. Used for padding. * @param stdClass $args An object of wp_nav_menu() arguments. */ $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args ); } }
Мы переопределили метод start_el()
класса Walker_Nav_Menu
. Потребовалось лишь несколько строк кода, чтобы добавить CSS-классы nav-item
и nav-link
:
// добавляем CSS-класс nav-item для элементов <li> $classes[] = 'nav-item'; // добавляем CSS-класс active для текущей страницы if ($item->current) { $classes[] = 'active'; }
// добавляем CSS-класс nav-link для ссылок $atts['class'] = 'nav-link';
Если прочие css-классы для элементов <li>
не нужны, чуть-чуть изменяем код:
// $classes = empty( $item->classes ) ? array() : (array) $item->classes; // $classes[] = 'menu-item-' . $item->ID; // добавляем CSS-класс nav-item для элементов <li> $classes = ['nav-item']; // добавляем CSS-класс active для текущей страницы if ($item->current) { $classes[] = 'active'; }
Подключаем файл с классом My_Walker_Nav_Menu
в файле functions.php
require_once __DIR__ . '/My_Walker_Nav_Menu.php';
И выводим меню, передавая объект этого класса параметру walker
:
<nav class="navbar navbar-expand-lg navbar-dark bg-primary"> <div class="container"> <a class="navbar-brand" href="<?= home_url(); ?>">Главная</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#main-menu" aria-controls="main-menu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <?php wp_nav_menu([ 'theme_location' => 'header_menu', 'container' => 'div', 'container_class' => 'collapse navbar-collapse', 'container_id' => 'main-menu', 'menu_class' => 'navbar-nav mr-auto', 'menu_id' => 'main-menu-ul', 'walker' => new My_Walker_Nav_Menu(), ]); ?> </div> </nav>
Использование функции wp_get_nav_menu_items()
Функция возвращает массив объектов элементов меню. Если меню не содержит элементов, возвращает пустой массив, либо false
, если указанного меню не существует.
wp_get_nav_menu_items($menu, $args = []);
$menu
(строка). Можно указатьID
,slug
или название меню, элементы которого нужно будет получить. Не указывайте здесь области темы.$args
(массив). Дополнительные параметры вывода.
По умолчанию параметр $args
принимает следующие значения:
$args = [ 'nopaging' => true, 'post_type' => 'nav_menu_item', 'post_status' => 'publish', 'order' => 'ASC', 'orderby' => 'menu_order', 'output' => ARRAY_A, 'output_key' => 'menu_order', 'update_post_term_cache' => false ];
Давайте по традиции добавим CSS-класс nav-item
для элементов <li>
и CSS-класс nav-link
для элементов <a>
:
<nav class="navbar navbar-expand-lg navbar-dark bg-primary"> <div class="container"> <a class="navbar-brand" href="<?= home_url(); ?>">Главная</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#main-menu" aria-controls="main-menu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <?php if ($items = wp_get_nav_menu_items('Главное меню')): ?> <div class="collapse navbar-collapse" id="main-menu"> <ul class="navbar-nav mr-auto"> <?php foreach ($items as $item): ?> <?php $current = get_queried_object_id() == $item->object_id; ?> <li class="nav-item<?= $current ? ' active' : ''; ?>"> <a class="nav-link" href="<?= $item->url; ?>"><?= $item->title; ?></a> </li> <?php endforeach; ?> </ul> </div> <?php endif; ?> </div> </nav>
Объект элемента меню:
WP_Post Object ( [ID] => 1911 [post_author] => 1 [post_date] => 2019-03-24 13:47:14 [post_date_gmt] => 2019-03-24 10:47:14 [post_content] => [post_title] => [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => 1911 [to_ping] => [pinged] => [post_modified] => 2019-03-25 11:58:47 [post_modified_gmt] => 2019-03-25 08:58:47 [post_content_filtered] => [post_parent] => 0 [guid] => http://www.server.com/?p=1911 [menu_order] => 1 [post_type] => nav_menu_item [post_mime_type] => [comment_count] => 0 [filter] => raw [db_id] => 1911 [menu_item_parent] => 0 [object_id] => 2 [object] => page [type] => post_type [type_label] => Страница [url] => http://www.server.com/about-author/ [title] => Об авторе блога [target] => [attr_title] => [description] => [classes] => Array ( [0] => ) [xfn] => )
Дополнительно
Поиск: CMS • Web-разработка • WordPress • Меню • Навигация • Walker_Nav_Menu • wp_get_nav_menu_items • wp_nav_menu • get_queried_object_id