WordPress как на ладони
Недорогой хостинг для сайтов на WordPress: wordpress.jino.ru

nav_menu_link_attributes хук-фильтр . WP 3.6.0

Позволяет изменить HTML атрибуты <a> элемента меню: title, target, rel, href.

По умолчанию эти атрибуты устанавливаются в админке в разделе редактирования меню:

Атрибут href является ссылкой и назначается автоматически на основе выбранного элемента (запись, рубрика и т.д.) или указывается вручную, если выбран элемент "Произвольная ссылка".

Использование

add_filter( 'nav_menu_link_attributes', 'filter_function_name_3020', 10, 4 );
function filter_function_name_3020( $atts, $item, $args, $depth ){
	// filter...

	return $atts;
}
$atts(массив)

HTML атрибуты <a> элемента меню. Атрибуты с пустыми значениями не будут выведены на экран.

  • $title (строка)
    Атрибут title. Например "Этот пункт очень важный".

  • $target (строка)
    Атрибут target. Например _blank.

  • $rel (строка)
    Атрибут rel. Например nofollow.

  • $href (строка)
    Атрибут href.
$item(WP_Post)

Объект текущего пункта меню. Пример:

WP_Post Object
(
	[ID] => 265
	[post_author] => 1
	[post_date] => 2018-04-07 09:45:46
	[post_date_gmt] => 2018-04-07 06:45:46
	[post_content] => 
	[post_title] => Обратная связь
	[post_excerpt] => 
	[post_status] => publish
	[comment_status] => closed
	[ping_status] => closed
	[post_password] => 
	[post_name] => 265
	[to_ping] => 
	[pinged] => 
	[post_modified] => 2018-04-19 00:20:29
	[post_modified_gmt] => 2018-04-18 21:20:29
	[post_content_filtered] => 
	[post_parent] => 0
	[guid] => http://wp-test.ru/?p=265
	[menu_order] => 1
	[post_type] => nav_menu_item
	[post_mime_type] => 
	[comment_count] => 0
	[filter] => raw
	[db_id] => 265
	[menu_item_parent] => 0
	[object_id] => 214
	[object] => page
	[type] => post_type
	[type_label] => Страница
	[url] => http://wp-test.ru/post-99
	[title] => Обратная связь
	[target] => 
	[attr_title] => 
	[description] => 
	[classes] => Array
		(
			[0] => 
			[1] => menu-item
			[2] => menu-item-type-post_type
			[3] => menu-item-object-page
		)

	[xfn] => 
	[current] => 
	[current_item_ancestor] => 
	[current_item_parent] => 
)
$args(stdClass)

Объект с аргументами из функции wp_nav_menu(). Пример:

stdClass Object
(
	[menu] => WP_Term Object
		(
			[term_id] => 21
			[name] => Моё первое меню
			[slug] => moe-pervoe-menu
			[term_group] => 0
			[term_taxonomy_id] => 21
			[taxonomy] => nav_menu
			[description] => 
			[parent] => 0
			[count] => 3
			[filter] => raw
		)

	[container] => div
	[container_class] => 
	[container_id] => 
	[menu_class] => primary-menu
	[menu_id] => 
	[echo] => 1
	[fallback_cb] => wp_page_menu
	[before] => 
	[after] => 
	[link_before] => 
	[link_after] => 
	[items_wrap] => <ul id="%1$s" class="%2$s">%3$s</ul>
	[item_spacing] => preserve
	[depth] => 0
	[walker] => 
	[theme_location] => primary
)
$depth(число)
Уровень пункта меню. Добавлен в версии 4.1.0. Используется для отступов. Верхние пункты меню имеют $depth = 0, вложенные в них $depth = 1 и так далее.

Примеры

#1 Открывать внешние ссылки в отдельной вкладке

add_filter( 'nav_menu_link_attributes', 'change_nav_menu_link_attributes' );

function change_nav_menu_link_attributes( $atts ) {
	if ( strpos( $atts['href'], home_url() ) === false ) {
		$atts['target'] = '_blank';
	}

	return $atts;
}

#2 Добавляет атрибут class активной ссылке

Этот пример показывает как можно дополнить список классов у элемента меню WordPress и добавить туда свой класс к текущему активному элементу меню.

// Добавляем классы ссылкам
add_filter( 'nav_menu_link_attributes', 'filter_nav_menu_link_attributes', 10, 4 );
function filter_nav_menu_link_attributes( $atts, $item, $args, $depth ) {

	if ( $item->current ) {
		$class = 'menu-link--active';
		$atts['class'] = isset( $atts['class'] ) ? "{$atts['class']} $class" : $class;
	}

	return $atts;
}

#3 Сделать все ссылки в меню относительными

Учитываем, что если будет ссылка на сторонний сайт wp_make_link_relative() её нужно пропустить.

add_filter( 'nav_menu_link_attributes', 'change_nav_menu_atts', 10, 2 );
function change_nav_menu_atts( $atts, $item ) {
	$atts['href'] = str_replace( home_url(), '', $item->url );

	return $atts;
}

Заметки

  • C версии 4.1.0 был добавлен параметр $depth.

Список изменений

С версии 3.6.0 Введена.
С версии 4.1.0 The $depth parameter was added.

Где вызывается хук

Walker_Nav_Menu::start_el()
nav_menu_link_attributes
wp-includes/class-walker-nav-menu.php 202
$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );

Где используется хук в ядре WP

Использование не найдено.
campusboy 3539youtube.com/c/wpplus
Создатель YouTube канала wp-plus, на котором делюсь своим опытом. Активный пользователь wp-kama.ru. WordPress-разработчик. Разработка сайтов и лендингов. Доработка существующих проектов. Сопровождение ресурсов.
Редакторы: Kama 7746
9 комментов
  • Alexandrov Yan40 codyshop.ru

    Еще примерчик. Сделать все ссылки в меню относительными:

    function change_nav_menu_atts( $atts, $item ) {
    	$atts['href'] = wp_make_link_relative ( $item->url );
    	return $atts;
    }
    add_filter( 'nav_menu_link_attributes', 'change_nav_menu_atts', 10, 2 );
    
    // Преобразует ссылку вида
    // http://site.ru/some-page/
    // в
    // /some-page/
    1
    Ответить20.Июн.2018 22:02 #
    • campusboy3539 www.youtube.com/c/wpplus

      Но если будет ссылка на сторонний сайт, то wp_make_link_relative() его тоже "порежет", верно?)

      Предлагаю такой вариант, чтобы внешние ссылки не обрезать:

      function change_nav_menu_atts( $atts, $item ) {
      	$atts['href'] = str_replace( home_url(), '', $item->url );
      
      	return $atts;
      }
      
      add_filter( 'nav_menu_link_attributes', 'change_nav_menu_atts', 10, 2 );
      1
      Ответить20.Июн.2018 22:04 #
  • Андрей

    Почему код из этого хука не обрабатывает ссылку самого верхнего уровня вложенности? ($depth=0). В подменю и под-подменю работает. Что делать с верхним уровнем???

    add_filter( 'nav_menu_link_attributes', 'filter_nav_menu_link_attributes', 10, 4 );
    function filter_nav_menu_link_attributes($atts, $item, $args, $depth){
    		if ($args->theme_location === 'header_menu'){
    			if ( $item->menu_item_parent ){
    				$atts['class'] = 'dropdown__link';
    			}
    		}
    		return $atts;
    }
    Ответить31.Мар.2019 20:12 #
    • campusboy3539 www.youtube.com/c/wpplus

      Почему же не обрабатывает? Обрабатывает. Просто ты указал условие: если у пункта меню есть родитель (то есть этот пункт меню дочерний), то присвоить такой-то класс. Понятное дело, что у пунктов меню с $depth=0 нет родителей, это ведь верхний уровень.

      Ответить13.Апр.2020 18:42 #
  • @ Сергей

    Отличный сайт. Часто пользуюсь примерами. Один пример у меня вызывал все время ошибку (не находил массив). В самом деле, если у ссылки нет атрибутов вообще, то лучше осуществить проверку. Здесь чуть поправил код из примера #2 Добавляет атрибут class активной ссылке ссылке

    /*Добавляем классы ссылкам*/
    add_filter( 'nav_menu_link_attributes', 'filter_nav_menu_link_attributes', 10, 4 );
    function filter_nav_menu_link_attributes( $atts, $item, $args, $depth ) { 
    	if ( $item->current ) {
    		if(!isset($atts)) {
    			$atts = array('class' => ' menu-link--active');
    		}
    		else {
    			$atts['class'] .= ' menu-link--active'';
    		}
    	}
    	return $atts;
    }
    1
    Ответить11.Апр.2020 21:53 #
    • campusboy3539 www.youtube.com/c/wpplus

      Спасибо за фидбек, поправил thank_you. Действительно, по умолчанию у ссылок меню нет атрибута class, поэтому надо проверять его наличие.

      если у ссылки нет атрибутов вообще, то лучше осуществить проверку

      Как у ссылки не может быть атрибутов вообще? А тот же url? Без него ссылка не ссылка.

      Ответить13.Апр.2020 15:38 #
  • Спасибо за статью. А можно ли добавить пользовательский класс всем ссылкам, а не только активным? Целый день бьюсь над этим, а наверняка есть какое-то немудреное решение.

    Ответить25.Май.2020 18:13 #
    • campusboy3539 www.youtube.com/c/wpplus

      Если не секрет, в чем сложность-то была? Если не надо условие, значит делать без условия. Логично? На основе 2 примера:

      // Добавляем классы ссылкам
      add_filter( 'nav_menu_link_attributes', 'filter_nav_menu_link_attributes', 10, 4 );
      function filter_nav_menu_link_attributes( $atts, $item, $args, $depth ) {
      	$class = 'menu-link';
      	$atts['class'] = isset( $atts['class'] ) ? "{$atts['class']} $class" : $class;
      
      	return $atts;
      }
      2
      Ответить25.Май.2020 19:08 #
      • Точно. Работает. Тупанул - не убрал "if ( $item->current )"...

        Campusboy, огромное спасибо!

        Ответить26.Май.2020 12:42 #