WordPress как на ладони
Готовые темы (шаблоны) для WordPress wordpress jino

Хлебные крошки для WordPress (breadcrumbs)

Вы наверняка уже знакомы с понятием «Хлебные крошки» в веб-разработке и возможно даже приходилось реализовывать эти самые «крошки» на WordPress.

Хлебные крошки (с англ. breadcrumbs) — это элемент навигации по сайту, выглядит как путь от главной страницы до текущей, на которой находится пользователь. Более логичное название — навигационная цепочка. Хлебные крошки называются так по ироничной аналогии со сказкой, в которой дети, когда их завели в лес во второй раз, не смогли найти обратную дорогу, так как на этот раз вместо маленьких камешков они оставляли за собой хлебные крошки, впоследствии склеванные лесными птицами.

Оглавление:

На вид «хлебные крошки» такие:

Главная страница » Раздел » Подраздел » Текущая страница

«Хлебные крошки» наиболее рекомендуются сайтам со сложной структурой разделов (рубрик), ведь с ними гораздо легче и понятнее разобраться посетителю в каком разделе сайта он находится и если нужно, можно легко подняться на уровень выше и осмотреть ветку целиком.

Теперь, после короткого ликбеза, я поделюсь с вами очередной свой функцией для WordPress, реализовывающей всю цепочку от главной страницы до текущей на всех типах страниц, включая таксономии и произвольные типы записей.

Функция будет показывать «хлебные крошки» для страниц следующих типов:
  • Главная страница;
  • Постоянная страница;
  • Страница любого древовидного типа записи;
  • Страница поста;
  • Страница вложения (учитывается прикреплено вложение к записи или нет);
  • Любой не древовидный тип записи (прикрепленный к любой таксономии, например, к стандартным "рубрикам");
  • Страница рубрики;
  • Страница меток;
  • Страница таксономии (как древовидной, так и одноуровневой (метки));
  • Страницы архивов по датам, авторам;
  • Страница пагинации для всех типов где предусмотрена пагинация
    (отображается как: Главная » Рубрика » Страница 2,3,4).
  • Поддерживает микроразметку. Инструменты для проверки: для Яндекса и для Google.

Из особенностей, которые я не встретил в аналогичных функциях представленных в сети, стоит отметить правильный показ "хлебных крошек" для произвольных типов записей и произвольных таксономий, также в аналогах страница пагинации отображалась как, например, "Рубрика (страница 2)", а не "Рубрика > Страница 2", что, на мой взгляд, неправильно.

Для визуального восприятия, взгляните как выглядят «хлебные крошки» разных типов страниц на этом блоге:

Хлебные крошки

Также, я старался написать как можно менее прожорливый вариант функции.

Что касается плагина Breadcrumb NavXT, который повсеместно рекомендуется для вывода «хлебных крошек» — он мне не понравился из-за своей громоздкости. Моя функция не хуже, а в чем-то даже лучше: за счет функциональности, компактности и местами быстродействия!

Также функция поддерживает микроразметки: schema.org или RDF, смотрите параметр 'markup'.

к началу

Функция «хлебных крошек» для WordPress

<?php

/**
 * Хлебные крошки для WordPress (breadcrumbs)
 *
 * @param  string [$sep  = '']      Разделитель. По умолчанию ' » '
 * @param  array  [$l10n = array()] Для локализации. См. переменную $default_l10n.
 * @param  array  [$args = array()] Опции. См. переменную $def_args
 * @return string Выводит на экран HTML код
 *
 * version 3.3.1
 */
function kama_breadcrumbs( $sep = ' » ', $l10n = array(), $args = array() ){
	$kb = new Kama_Breadcrumbs;
	echo $kb->get_crumbs( $sep, $l10n, $args );
}

class Kama_Breadcrumbs {

	public $arg;

	// Локализация
	static $l10n = array(
		'home'       => 'Главная',
		'paged'      => 'Страница %d',
		'_404'       => 'Ошибка 404',
		'search'     => 'Результаты поиска по запросу - <b>%s</b>',
		'author'     => 'Архив автора: <b>%s</b>',
		'year'       => 'Архив за <b>%d</b> год',
		'month'      => 'Архив за: <b>%s</b>',
		'day'        => '',
		'attachment' => 'Медиа: %s',
		'tag'        => 'Записи по метке: <b>%s</b>',
		'tax_tag'    => '%1$s из "%2$s" по тегу: <b>%3$s</b>',
		// tax_tag выведет: 'тип_записи из "название_таксы" по тегу: имя_термина'.
		// Если нужны отдельные холдеры, например только имя термина, пишем так: 'записи по тегу: %3$s'
	);

	// Параметры по умолчанию
	static $args = array(
		'on_front_page'   => true,  // выводить крошки на главной странице
		'show_post_title' => true,  // показывать ли название записи в конце (последний элемент). Для записей, страниц, вложений
		'show_term_title' => true,  // показывать ли название элемента таксономии в конце (последний элемент). Для меток, рубрик и других такс
		'title_patt'      => '<span class="kb_title">%s</span>', // шаблон для последнего заголовка. Если включено: show_post_title или show_term_title
		'last_sep'        => true,  // показывать последний разделитель, когда заголовок в конце не отображается
		'markup'          => 'schema.org', // 'markup' - микроразметка. Может быть: 'rdf.data-vocabulary.org', 'schema.org', '' - без микроразметки
										   // или можно указать свой массив разметки:
										   // array( 'wrappatt'=>'<div class="kama_breadcrumbs">%s</div>', 'linkpatt'=>'<a href="%s">%s</a>', 'sep_after'=>'', )
		'priority_tax'    => array('category'), // приоритетные таксономии, нужно когда запись в нескольких таксах
		'priority_terms'  => array(), // 'priority_terms' - приоритетные элементы таксономий, когда запись находится в нескольких элементах одной таксы одновременно.
									  // Например: array( 'category'=>array(45,'term_name'), 'tax_name'=>array(1,2,'name') )
									  // 'category' - такса для которой указываются приор. элементы: 45 - ID термина и 'term_name' - ярлык.
									  // порядок 45 и 'term_name' имеет значение: чем раньше тем важнее. Все указанные термины важнее неуказанных...
		'nofollow' => false, // добавлять rel=nofollow к ссылкам?

		// служебные
		'sep'             => '',
		'linkpatt'        => '',
		'pg_end'          => '',
	);

	function get_crumbs( $sep, $l10n, $args ){
		global $post, $wp_query, $wp_post_types;

		self::$args['sep'] = $sep;

		// Фильтрует дефолты и сливает
		$loc = (object) array_merge( apply_filters('kama_breadcrumbs_default_loc', self::$l10n ), $l10n );
		$arg = (object) array_merge( apply_filters('kama_breadcrumbs_default_args', self::$args ), $args );

		$arg->sep = '<span class="kb_sep">'. $arg->sep .'</span>'; // дополним

		// упростим
		$sep = & $arg->sep;
		$this->arg = & $arg;

		// микроразметка ---
		if(1){
			$mark = & $arg->markup;

			// Разметка по умолчанию
			if( ! $mark ) $mark = array(
				'wrappatt'  => '<div class="kama_breadcrumbs">%s</div>',
				'linkpatt'  => '<a href="%s">%s</a>',
				'sep_after' => '',
			);
			// rdf
			elseif( $mark === 'rdf.data-vocabulary.org' ) $mark = array(
				'wrappatt'   => '<div class="kama_breadcrumbs" prefix="v: http://rdf.data-vocabulary.org/#">%s</div>',
				'linkpatt'   => '<span typeof="v:Breadcrumb"><a href="%s" rel="v:url" property="v:title">%s</a>',
				'sep_after'  => '</span>', // закрываем span после разделителя!
			);
			// schema.org
			elseif( $mark === 'schema.org' ) $mark = array(
				'wrappatt'   => '<div class="kama_breadcrumbs" itemscope itemtype="http://schema.org/BreadcrumbList">%s</div>',
				'linkpatt'   => '<span itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a href="%s" itemprop="item"><span itemprop="name">%s</span></a></span>',
				'sep_after'  => '',
			);

			elseif( ! is_array($mark) )
				die( __CLASS__ .': "markup" parameter must be array...');

			$wrappatt  = $mark['wrappatt'];
			$arg->linkpatt  = $arg->nofollow ? str_replace('<a ','<a rel="nofollow"', $mark['linkpatt']) : $mark['linkpatt'];
			$arg->sep      .= $mark['sep_after']."\n";
		}

		$linkpatt = $arg->linkpatt; // упростим

		$q_obj = get_queried_object();

		// может это архив пустой таксы?
		$ptype = null;
		if( empty($post) ){
			if( isset($q_obj->taxonomy) )
				$ptype = & $wp_post_types[ get_taxonomy($q_obj->taxonomy)->object_type[0] ];
		}
		else $ptype = & $wp_post_types[ $post->post_type ];

		// paged
		$arg->pg_end = '';
		if( ($paged_num = get_query_var('paged')) || ($paged_num = get_query_var('page')) )
			$arg->pg_end = $sep . sprintf( $loc->paged, (int) $paged_num );

		$pg_end = $arg->pg_end; // упростим

		// ну, с богом...
		$out = '';

		if( is_front_page() ){
			return $arg->on_front_page ? sprintf( $wrappatt, ( $paged_num ? sprintf($linkpatt, get_home_url(), $loc->home) . $pg_end : $loc->home ) ) : '';
		}
		// страница записей, когда для главной установлена отдельная страница.
		elseif( is_home() ) {
			$out = $paged_num ? ( sprintf( $linkpatt, get_permalink($q_obj), esc_html($q_obj->post_title) ) . $pg_end ) : esc_html($q_obj->post_title);
		}
		elseif( is_404() ){
			$out = $loc->_404;
		}
		elseif( is_search() ){
			$out = sprintf( $loc->search, esc_html( $GLOBALS['s'] ) );
		}
		elseif( is_author() ){
			$tit = sprintf( $loc->author, esc_html($q_obj->display_name) );
			$out = ( $paged_num ? sprintf( $linkpatt, get_author_posts_url( $q_obj->ID, $q_obj->user_nicename ) . $pg_end, $tit ) : $tit );
		}
		elseif( is_year() || is_month() || is_day() ){
			$y_url  = get_year_link( $year = get_the_time('Y') );

			if( is_year() ){
				$tit = sprintf( $loc->year, $year );
				$out = ( $paged_num ? sprintf($linkpatt, $y_url, $tit) . $pg_end : $tit );
			}
			// month day
			else {
				$y_link = sprintf( $linkpatt, $y_url, $year);
				$m_url  = get_month_link( $year, get_the_time('m') );

				if( is_month() ){
					$tit = sprintf( $loc->month, get_the_time('F') );
					$out = $y_link . $sep . ( $paged_num ? sprintf( $linkpatt, $m_url, $tit ) . $pg_end : $tit );
				}
				elseif( is_day() ){
					$m_link = sprintf( $linkpatt, $m_url, get_the_time('F'));
					$out = $y_link . $sep . $m_link . $sep . get_the_time('l');
				}
			}
		}
		// Древовидные записи
		elseif( is_singular() && $ptype->hierarchical ){
			$out = $this->_add_title( $this->_page_crumbs($post), $post );
		}
		// Таксы, плоские записи и вложения
		else {
			$term = $q_obj; // таксономии

			// определяем термин для записей (включая вложения attachments)
			if( is_singular() ){
				// изменим $post, чтобы определить термин родителя вложения
				if( is_attachment() && $post->post_parent ){
					$save_post = $post; // сохраним
					$post = get_post($post->post_parent);
				}

				// учитывает если вложения прикрепляются к таксам древовидным - все бывает :)
				$taxonomies = get_object_taxonomies( $post->post_type );
				// оставим только древовидные и публичные, мало ли...
				$taxonomies = array_intersect( $taxonomies, get_taxonomies( array('hierarchical' => true, 'public' => true) ) );

				if( $taxonomies ){
					// сортируем по приоритету
					if( ! empty($arg->priority_tax) ){
						usort( $taxonomies, function($a,$b)use($arg){
							$a_index = array_search($a, $arg->priority_tax);
							if( $a_index === false ) $a_index = 9999999;

							$b_index = array_search($b, $arg->priority_tax);
							if( $b_index === false ) $b_index = 9999999;

							return ( $b_index === $a_index ) ? 0 : ( $b_index < $a_index ? 1 : -1 ); // меньше индекс - выше
						} );
					}

					// пробуем получить термины, в порядке приоритета такс
					foreach( $taxonomies as $taxname ){
						if( $terms = get_the_terms( $post->ID, $taxname ) ){
							// проверим приоритетные термины для таксы
							$prior_terms = & $arg->priority_terms[ $taxname ];
							if( $prior_terms && count($terms) > 2 ){
								foreach( (array) $prior_terms as $term_id ){
									$filter_field = is_numeric($term_id) ? 'term_id' : 'slug';
									$_terms = wp_list_filter( $terms, array($filter_field=>$term_id) );

									if( $_terms ){
										$term = array_shift( $_terms );
										break;
									}
								}
							}
							else
								$term = array_shift( $terms );

							break;
						}
					}
				}

				if( isset($save_post) ) $post = $save_post; // вернем обратно (для вложений)
			}

			// вывод

			// все виды записей с терминами или термины
			if( $term && isset($term->term_id) ){
				$term = apply_filters('kama_breadcrumbs_term', $term );

				// attachment
				if( is_attachment() ){
					if( ! $post->post_parent )
						$out = sprintf( $loc->attachment, esc_html($post->post_title) );
					else {
						if( ! $out = apply_filters('attachment_tax_crumbs', '', $term, $this ) ){
							$_crumbs    = $this->_tax_crumbs( $term, 'self' );
							$parent_tit = sprintf( $linkpatt, get_permalink($post->post_parent), get_the_title($post->post_parent) );
							$_out = implode( $sep, array($_crumbs, $parent_tit) );
							$out = $this->_add_title( $_out, $post );
						}
					}
				}
				// single
				elseif( is_single() ){
					if( ! $out = apply_filters('post_tax_crumbs', '', $term, $this ) ){
						$_crumbs = $this->_tax_crumbs( $term, 'self' );
						$out = $this->_add_title( $_crumbs, $post );
					}
				}
				// не древовидная такса (метки)
				elseif( ! is_taxonomy_hierarchical($term->taxonomy) ){
					// метка
					if( is_tag() )
						$out = $this->_add_title('', $term, sprintf( $loc->tag, esc_html($term->name) ) );
					// такса
					elseif( is_tax() ){
						$post_label = $ptype->labels->name;
						$tax_label = $GLOBALS['wp_taxonomies'][ $term->taxonomy ]->labels->name;
						$out = $this->_add_title('', $term, sprintf( $loc->tax_tag, $post_label, $tax_label, esc_html($term->name) ) );
					}
				}
				// древовидная такса (рибрики)
				else {
					if( ! $out = apply_filters('term_tax_crumbs', '', $term, $this ) ){
						$_crumbs = $this->_tax_crumbs( $term, 'parent' );
						$out = $this->_add_title( $_crumbs, $term, esc_html($term->name) );                     
					}
				}
			}
			// влоежния от записи без терминов
			elseif( is_attachment() ){
				$parent = get_post($post->post_parent);
				$parent_link = sprintf( $linkpatt, get_permalink($parent), esc_html($parent->post_title) );
				$_out = $parent_link;

				// вложение от записи древовидного типа записи
				if( is_post_type_hierarchical($parent->post_type) ){
					$parent_crumbs = $this->_page_crumbs($parent);
					$_out = implode( $sep, array( $parent_crumbs, $parent_link ) );
				}

				$out = $this->_add_title( $_out, $post );
			}
			// записи без терминов
			elseif( is_singular() ){
				$out = $this->_add_title( '', $post );
			}
		}

		// замена ссылки на архивную страницу для типа записи
		$home_after = apply_filters('kama_breadcrumbs_home_after', '', $linkpatt, $sep, $ptype );

		if( '' === $home_after ){
			// Ссылка на архивную страницу типа записи для: отдельных страниц этого типа; архивов этого типа; таксономий связанных с этим типом.
			if( $ptype && $ptype->has_archive && ! in_array( $ptype->name, array('post','page','attachment') )
				&& ( is_post_type_archive() || is_singular() || (is_tax() && in_array($term->taxonomy, $ptype->taxonomies)) )
			){
				$pt_title = $ptype->labels->name;

				// первая страница архива типа записи
				if( is_post_type_archive() && ! $paged_num )
					$home_after = $pt_title;
				// singular, paged post_type_archive, tax
				else{
					$home_after = sprintf( $linkpatt, get_post_type_archive_link($ptype->name), $pt_title );

					$home_after .= ( ($paged_num && ! is_tax()) ? $pg_end : $sep ); // пагинация
				}
			}
		}

		$before_out = sprintf( $linkpatt, home_url(), $loc->home ) . ( $home_after ? $sep.$home_after : ($out ? $sep : '') );

		$out = apply_filters('kama_breadcrumbs_pre_out', $out, $sep, $loc, $arg );

		$out = sprintf( $wrappatt, $before_out . $out );

		return apply_filters('kama_breadcrumbs', $out, $sep, $loc, $arg );
	}

	function _page_crumbs( $post ){
		$parent = $post->post_parent;

		$crumbs = array();
		while( $parent ){
			$page = get_post( $parent );
			$crumbs[] = sprintf( $this->arg->linkpatt, get_permalink($page), esc_html($page->post_title) );
			$parent = $page->post_parent;
		}

		return implode( $this->arg->sep, array_reverse($crumbs) );
	}

	function _tax_crumbs( $term, $start_from = 'self' ){
		$termlinks = array();
		$term_id = ($start_from === 'parent') ? $term->parent : $term->term_id;
		while( $term_id ){
			$term       = get_term( $term_id, $term->taxonomy );
			$termlinks[] = sprintf( $this->arg->linkpatt, get_term_link($term), esc_html($term->name) );
			$term_id    = $term->parent;
		}

		if( $termlinks )
			return implode( $this->arg->sep, array_reverse($termlinks) ) /*. $this->arg->sep*/;
		return '';
	}

	// добалвяет заголовок к переданному тексту, с учетом всех опций. Добавляет разделитель в начало, если надо.
	function _add_title( $add_to, $obj, $term_title = '' ){
		$arg = & $this->arg; // упростим...
		$title = $term_title ? $term_title : esc_html($obj->post_title); // $term_title чиститься отдельно, теги моугт быть...
		$show_title = $term_title ? $arg->show_term_title : $arg->show_post_title;

		// пагинация
		if( $arg->pg_end ){
			$link = $term_title ? get_term_link($obj) : get_permalink($obj);
			$add_to .= ($add_to ? $arg->sep : '') . sprintf( $arg->linkpatt, $link, $title ) . $arg->pg_end;
		}
		// дополняем - ставим sep
		elseif( $add_to ){
			if( $show_title )
				$add_to .= $arg->sep . sprintf( $arg->title_patt, $title );
			elseif( $arg->last_sep )
				$add_to .= $arg->sep;
		}
		// sep будет потом...
		elseif( $show_title )
			$add_to = sprintf( $arg->title_patt, $title );

		return $add_to;
	}

}

/**
 * Изменения:
 * 3.3 - новые хуки: attachment_tax_crumbs, post_tax_crumbs, term_tax_crumbs. Позволяют дополнить крошки таксономий.
 * 3.2 - баг с разделителем, с отключенным 'show_term_title'. Стабилизировал логику.
 * 3.1 - баг с esc_html() для заголовка терминов - с тегами получалось криво...
 * 3.0 - Обернул в класс. Добавил опции: 'title_patt', 'last_sep'. Доработал код. Добавил пагинацию для постов.
 * 2.5 - ADD: Опция 'show_term_title'
 * 2.4 - Мелкие правки кода
 * 2.3 - ADD: Страница записей, когда для главной установлена отделенная страница.
 * 2.2 - ADD: Link to post type archive on taxonomies page
 * 2.1 - ADD: $sep, $loc, $args params to hooks
 * 2.0 - ADD: в фильтр 'kama_breadcrumbs_home_after' добавлен четвертый аргумент $ptype
 * 1.9 - ADD: фильтр 'kama_breadcrumbs_default_loc' для изменения локализации по умолчанию
 * 1.8 - FIX: заметки, когда в рубрике нет записей
 * 1.7 - Улучшена работа с приоритетными таксономиями.
 */

Вставлять этот код нужно в файл шаблона functions.php или непосредственно в тот файл где вызывается функция.

Вызывать функцию нужно в шаблоне, в том месте, где должны выводится крошки, так:

<?php if( function_exists('kama_breadcrumbs') ) kama_breadcrumbs(); ?>

Если нужно поменять разделитель между ссылками, укажите первый параметр:

<?php if( function_exists('kama_breadcrumbs') ) kama_breadcrumbs(' » '); ?>
к началу

Примеры использование фильтров

#1 Установка параметров через фильтр

Измени дефолтные параметры через фильтр

add_filter('kama_breadcrumbs_default_args', function($args){
	$args['on_front_page']   = 0;
	$args['show_post_title'] = '';
	$args['priority_tax']    = array('mytax');
	return $args;
} );

Если установить параметры при вызове функции в третьем аргументе функции, то они перебьют параметры указанные в фильтре...

#3 Пример перевода крошек на английский

Эти примеры показывают как перевести крошки на нужный язык или просто изменить дефолтные значения:

Вариант 1

При вызове функции нужно указать строки локализации так:

// Локализация
if( function_exists('kama_breadcrumbs') ){

	$myl10n = array(
		'home'       => 'Front page',
		'paged'      => 'Page %d',
		'_404'       => 'Error 404',
		'search'     => 'Search results by query - <b>%s</b>',
		'author'     => 'Author archve: <b>%s</b>',
		'year'       => 'Archive by <b>%d</b> год',
		'month'      => 'Archive by: <b>%s</b>',
		'day'        => '',
		'attachment' => 'Media: %s',
		'tag'        => 'Posts by tag: <b>%s</b>',
		'tax_tag'    => '%1$s from "%2$s" by tag: <b>%3$s</b>',
		// tax_tag выведет: 'тип_записи из "название_таксы" по тегу: имя_термина'. 
		// Если нужны отдельные холдеры, например только имя термина, пишем так: 'записи по тегу: %3$s'
	);

	kama_breadcrumbs(' » ', $myl10n );

}
Вариант 2

C версии 1.9. Можно использовать хук kama_breadcrumbs_default_loc, чтобы для каждого вызова одно и тоже не указывать. Для этого рядом с исходным кодом крошек добавьте такой хук:

add_filter('kama_breadcrumbs_default_loc', function($l10n){
	// Локализация
	return array(
		'home'       => 'Front page',
		'paged'      => 'Page %d',
		'_404'       => 'Error 404',
		'search'     => 'Search results by query - <b>%s</b>',
		'author'     => 'Author archve: <b>%s</b>',
		'year'       => 'Archive by <b>%d</b> год',
		'month'      => 'Archive by: <b>%s</b>',
		'day'        => '',
		'attachment' => 'Media: %s',
		'tag'        => 'Posts by tag: <b>%s</b>',
		'tax_tag'    => '%1$s from "%2$s" by tag: <b>%3$s</b>',
		// tax_tag выведет: 'тип_записи из "название_таксы" по тегу: имя_термина'. 
		// Если нужны отдельные холдеры, например только имя термина, пишем так: 'записи по тегу: %3$s'
	);
});

Далее, используйте вызов в шаблоне как обычно, крошки будут переведены на англ.:

function_exists('kama_breadcrumbs') && kama_breadcrumbs();

Установки через хук имеют меньший приоритет, чем через вызов функции из варианта 1. Это значит, что если указать локализацию через хук, то потом через вызов можно перебить локализацию отдельных строк.

#3 Добавление произвольной ссылки в начало крошек

Допустим нам нужно добавить после пункта "Главная" ссылку на страницу 7, если в текущий момент мы находимся в категории 5 или в её дочерней категории (учитывается один уровень вложенности).

Для этого добавьте такой хук рядом с кодом крошек:

add_action('kama_breadcrumbs_home_after', 'my_breadcrumbs_home_after', 10, 4);
function my_breadcrumbs_home_after( $false, $linkpatt, $sep, $ptype ){
	// если мы в рубрике с ID 5 или в дочерней рубрике,
	// то дополним начало крошек ссылкой на страницу с ID 7
	$qo = get_queried_object();
	if( is_category() && ( $qo->term_id == 5 || $qo->parent == 5 ) ){
		$page = get_post( 7 );
		return sprintf( $linkpatt, get_permalink($page), $page->post_title ) . $sep;
	}

	return $false;
}

#4 Добавление еще таксономий в крошки

По умолчанию в крошках обрабатывается только одна таксономи. Но иногда нужно несколько, для этого в версии 3.3 я вставил хуки: 'attachment_tax_crumbs', 'post_tax_crumbs', 'term_tax_crumbs'.

Допустим, у нас есть тип записи realty и 3 таксы для него: country, type_deal, type_realty. Нужно, чтобы у страницы записи в крошках отображались все таксы в указанном порядке. Также нужно, чтобы на каждой странице таксы указывались все предыдущие таксы и текущая в указанном порядке: country > type_deal > type_realty...

// apply_filters('term_tax_crumbs', '', $term, $that );
add_filter('term_tax_crumbs', 'more_tax_crumbs', 10, 3);
add_filter('post_tax_crumbs', 'more_tax_crumbs', 10, 3);
function more_tax_crumbs( $empty, $term, $that ){
	$is_post_filter = doing_filter('post_tax_crumbs'); // else 'term_tax_crumbs'

	if(  ( $is_post_filter && is_singular('realty') ) || is_tax('country') ){
		global $post;

		$out = '';

		$out = $that->_tax_crumbs( $term, 'self' ) . $that->arg->sep; // базовая такса - country

		// тип сделки
		$term = get_query_var('type_deal');
		if( $term && ($term = get_term_by('slug', $term, 'type_deal')) )
			$out .= $that->_tax_crumbs( $term, 'self' ) . $that->arg->sep; // тип сделки

		// тип недвижимости
		$term = get_query_var('type_realty');
		if( $term && ($term = get_term_by('slug', $term, 'type_realty')) ){
			// запись
			if( $is_post_filter ){
				$_crumbs = $that->_tax_crumbs( $term, 'self' );
				$out .= $that->_add_title( $_crumbs, $post );   
			}
			// такса
			else {
				$_crumbs = $that->_tax_crumbs( $term, 'parent' );
				$out .= $that->_add_title( $_crumbs, $term, esc_html($term->name) );                
			}

		}

		return $out;
	}

	return $empty;
}
к началу

Другой вариант крошек

Этот вариант я стянул по ссылке, которую в комментариях дал Master. Весьма занимательное решение, потому и не удержался.

Условно, этот код подойдет не только к WordPress, а вообще к любому движку. Для WordPress он подойдет:

  • во-первых, если включены ЧПУ;
  • во-вторых, если в ссылках присутствуют названия категории;
  • в-третьих, если названия статей и категорий в УРЛ пишутся в кириллице или это вообще англ. блог.

В других случаях будет работать, но, думаю, как-то не круто получится. Такие условия, потому что этот вариант разбирает ссылку на страницу (УРЛ) и по её элементам создает хлебные крошки. Ссылка разбивается разделителем /.

Допустим у нас УРЛ на статью имеет вид:
http://wptest.ru/рецепты/торт/готовим наполеон
тогда, мы получим цепочку крошек вида:
Главная » Рецепты » Торт » Готовим наполеон

function breadcrumbs($separator = ' » ', $home = 'Главная') {

	$path = array_filter(explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
	$base_url = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/';
	$breadcrumbs = array("<a href=\"$base_url\">$home</a>");

	$last = end( array_keys($path) );

	foreach( $path as $x => $crumb ){
		$title = ucwords(str_replace(array('.php', '_'), Array('', ' '), $crumb));
		if( $x != $last ){
			$breadcrumbs[] = '<a href="'.$base_url.$crumb.'">'.$title.'</a>';
		}
		else {
			$breadcrumbs[] = $title;
		}
	}

	return implode( $separator, $breadcrumbs );
}

Используется аналогично моей функции, только на экран выводить надо через echo:

<?php echo breadcrumbs(' » '); ?>
Хлебные крошки для WordPress (breadcrumbs) 468 комментариев
Полезные 25 Вопросы 13 Все
  • Тимур cайт: wp-masters.ru

    Добрый день, Тимур.
    Очень благодарен за функцию, конечно невероятно огромная О_О )) но похоже на все случаи "жизни" сайта ))

    Ответитьсейчас #

Здравствуйте, !

Ваш комментарий