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