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

Добавляем поиск по метаполю в обычный поиск WordPress

Базовый поиск WordPress ищет указанный текст в заголовке, контенте и отрывке (в полях post_title, post_content, post_excerpt). Ниже показано, как к этим базовым полям поиска добавить поиск и по метаполю. Т.е. ниже будем решать задача: как в стандартный поиск по записям добавить поиск по указанному метаполю.

Решение задачи на хуке posts_clauses

add_filter( 'posts_clauses', 'km_metadata_search' );

# Добавляем поиск по метаполям в базовый поиск WordPress
function km_metadata_search( $clauses ){
	global $wpdb;

	if( ! is_search() || ! is_main_query() )
		return $clauses;

	$clauses['join'] .= " LEFT JOIN $wpdb->postmeta kmpm ON (ID = kmpm.post_id)";

	$clauses['where'] = preg_replace(
		"/OR +\( *$wpdb->posts.post_content +LIKE +('[^']+')/",
		"OR (kmpm.meta_value LIKE $1) $0",
		$clauses['where']
	);

	// если нужно искать в указанном метаполе
	//$clauses['where'] .= $wpdb->prepare(' AND kmpm.meta_key = %s', 'my_meta_key' );

	$clauses['distinct'] = 'DISTINCT';

	// дебаг итогового запроса
	0 && add_filter( 'posts_request', function( $sql ){   die( $sql );  } );

	return $clauses;
}

Что делается в коде:

Шаг 1: Добавление таблицы метаданных в запрос (JOIN)

Расширим базовую таблицу posts, добавим к ней таблицу метаданных. Нужно это для того, чтобы появилась возможность указать поле таблицы метаполей в котором нужно искать. Поле указываем во втором шаге.

Шаг 2: Изменение выборки в запросе (WHERE)

Дополним WHERE часть запроса, чтобы "стандартный поиск" в дополнение искал ещё и по всем метаполям постов.

Шаг 3: Изменение выборки в запросе (DISTINCT)

Из-за LEFT JOIN в 1 шаге могут появится дубликаты. Избавимся от них.

Решение задачи на хуках: posts_join, posts_where, posts_distinct

add_filter( 'posts_join', 'cf_search_join' );
add_filter( 'posts_where', 'cf_search_where' );
add_filter( 'posts_distinct', 'cf_search_distinct' );

# Объединяет таблицы записей и таблиц метаданных.
function cf_search_join( $join ){
	global $wpdb;

	if( is_search() )
		$join .= " LEFT JOIN $wpdb->postmeta ON ID = $wpdb->postmeta.post_id ";

	return $join;
}

# Указывает по каким метаполям и какое значение искать в секции WHERE.
function cf_search_where( $where ){
	global $wpdb;

	if ( is_search() ) {
		$where = preg_replace(
			"/\(\s*$wpdb->posts.post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
			"($wpdb->posts.post_title LIKE $1) OR ($wpdb->postmeta.meta_value LIKE $1)", $where );
	}

	return $where;
}

# Предотвращает появление дубликатов в выборке.
function cf_search_distinct( $where ){
	return is_search() ? 'DISTINCT' : $where;
}

Фильтры работать не будут, если для запроса включен параметр suppress_filters.

Для запроса get_posts() фильтр работать не будет - там этот параметр включен по умолчанию!

-

При создании кода, была использована статья: adambalee.com

campusboy 3542youtube.com/c/wpplus
Создатель YouTube канала wp-plus, на котором делюсь своим опытом. Активный пользователь wp-kama.ru. WordPress-разработчик. Разработка сайтов и лендингов. Доработка существующих проектов. Сопровождение ресурсов.
Редакторы: Kama 7751
5 комментов
  • Добрый день. Пробовал и ваш вариант и ( Адама adambalee.com )
    Проблема такая, в результатах поиска страницы, содержащие метаполя находятся, но не отображается содержимое метаполей!
    Есть метаполе "Повторитель" из плагина ACF, и в нем вкладки. Так вот их содержимое не показывается.

    1
    Ответить10.Сен.2019 22:11 #
  • Поиск по произвольным полям работает, но у меня отключен поиск по заголовкам, в итоге если использовать оба этих кода, то полностью меняется сам принцип поиска. Вместо поиска по точному сочетанию поисковой фразы, вордпресс выдает все посты где встречается хотя бы одно слово из поисковой фразы.

    Ответить6.Ноя.2019 14:49 #
    • Kama7751

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

      Это базовое поведение поиска в ВП. Чтобы в ВП искать по точной фразе, нужно фразу взять в кавычки.

      Ответить20.Дек.2019 17:32 #
  • Никита

    Здравствуйте, я новичок в wordpress. Мне нужно сделать так, чтобы стандартный поиск моего шаблона осуществлял поиск и по метаданным. Куда мне нужно добавить Ваш код?

    Ответить15.Апр.2020 19:47 #