Додаємо пошук по метаполі у звичайний пошук 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_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_titles+LIKEs*('[^']+')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

Залишити коментар

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *