Добавляем поиск по метаполю в обычный поиск 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() фильтр работать не будет - там этот параметр включен по умолчанию!
--
При создании кода, была использована статья: http://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/