Добавление поиска по метаполям в стандартный поиск WordPress
Стандартный поиск WordPress ищет указанный текст в заголовке, содержании и отрывке записи (в полях post_title
, post_content
, post_excerpt
). В этой статье мы рассмотрим, как добавить поиск по указанным метаполям в стандартный поиск записей.
Как это работает: использование хука posts_clauses
Давайте начнём с добавления функциональности поиска по метаполям с помощью хука posts_clauses
.
Код для добавления поиска по метаполям
add_filter( 'posts_clauses', 'km_metadata_search' );
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['distinct'] = 'DISTINCT';
return $clauses;
}
Что делает этот код
-
Добавление таблицы метаданных к запросу (JOIN):
- Мы расширяем базовую таблицу записей, добавляя к ней таблицу метаданных. Это нужно, чтобы указать, по какому полю в таблице метаданных мы будем искать.
-
Модификация условий запроса (WHERE):
- Мы добавляем условие в секцию WHERE, чтобы стандартный поиск также искал в всех полях метаданных постов.
-
Избежание дубликатов (DISTINCT):
- При LEFT JOIN могут появляться дубликаты. Мы используем DISTINCT, чтобы избавиться от них.
Альтернативный способ: использование хуков 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;
}
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()
, так как этот параметр включен по умолчанию.
Заключение
Теперь вы знаете, как добавить функциональность поиска по метаполям в стандартный поиск WordPress. Это полезно, если вам нужно, чтобы пользователи могли находить записи не только по заголовкам и содержимому, но и по дополнительной информации, которую вы храните в метаполях.