Включение в поиск метаполей
// Добавляем в поиск метаполе
function me_search_query( $query ) {
if ( $query->is_search ) {
$meta_query_args = array(
array(
'key' => 'meta_key', //нужное поле
'value' => $query->query_vars['s'],
'compare' => 'LIKE',
),
);
$query->set('meta_query', $meta_query_args);
add_filter( 'get_meta_sql', 'me_replace_and_with_or' );
};
}
function me_replace_and_with_or( $sql ) {
if ( 1 === strpos( $sql['where'], 'AND' ) ) {
$sql['where'] = substr( $sql['where'], 4 );
$sql['where'] = ' OR ' . $sql['where'];
}
//make sure that this filter will fire only once for the meta query
remove_filter( 'get_meta_sql', 'me_replace_and_with_or' );
return $sql;
}
add_filter( 'pre_get_posts', 'me_search_query');
Правильный способ
Не могу сказать насчет оптимизации запроса с точки зрения обращения к базе данных, но я смог добиться нужного результата. Создав в pre_get_posts 2 запроса с условием: один обычный и один по метаполю, в результате получаем либо записи по запросу (стандартный поиск), либо записи по метаполю.
remove_action( ‘pre_get_posts’, __FUNCTION__ ); — обязательно, иначе будет бесконечный цикл и сервер вернет 502 Bad Gateway.
function custom_search_query( $query ) {
if ( !is_admin() && $query->is_search ) {
remove_action( 'pre_get_posts', __FUNCTION__ ); // чтобы не было бесконечного цикла
$search = get_posts( array(
's' => get_query_var('s'),
'posts_per_page' => -1,
'fields' => 'ids'
) );
if (empty($search)) {
$search = get_posts( array(
'meta_query' => array( array(
'key' => 'sku',
'value' => get_query_var('s'),
'compare' => 'LIKE'
) ),
'posts_per_page' => -1,
'fields' => 'ids'
) );
}
if (!empty($search)) {
$query->set('s', ''); //отключаем поиск по слову
$query->set('post__in', $search);
$query->set('post_type', 'post');
}
};
}
add_filter( 'pre_get_posts', 'custom_search_query');
Изначально я прорабатывал это методом объединения двух массивов, но подумал что это более затратно по запросам:
function custom_search_query( $query ) {
if ( !is_admin() && $query->is_search ) {
remove_action( 'pre_get_posts', __FUNCTION__ ); // чтобы не было бесконечного цикла
$search = get_posts( array(
's' => get_query_var('s'),
'posts_per_page' => -1,
'fields' => 'ids'
) );
$second = get_posts( array(
'meta_query' => array( array(
'key' => 'sku',
'value' => get_query_var('s'),
) ),
'posts_per_page' => -1,
'fields' => 'ids'
) );
$result = array_merge($first, $second);
$query->set('s', '');
$query->set('post__in', $result);
$query->set('post_type', 'post');
};
}
add_filter( 'pre_get_posts', 'custom_search_query');
Но может быть как метод где-нибудь пригодится.
Поиск только по метаполю
Данная функция отключает поиск по слову в заголовке записи и ищет по соответствию значения в метаполе.
function custom_search_query( $query ) {
if ( !is_admin() && $query->is_search ) {
global $wp_query;
if ($wp_query->post_count == 0) {
$query->set('meta_query', array(
array(
'key' => 'sku',
'value' => get_query_var('s'),
'compare' => 'IN'
)
));
//$query->set('post_type', 'post');
$query->set( 's', ''); // отключаем поиск по слову
}
};
}
add_filter( 'pre_get_posts', 'custom_search_query');
Правильное изменение поиска
function custom_search_query( $query ) {
if ( !is_admin() && $query->is_search ) {
remove_action( 'pre_get_posts', __FUNCTION__ ); // чтобы не было бесконечного цикла
$search = get_posts( array(
's' => get_query_var('s'),
'posts_per_page' => -1,
'fields' => 'ids'
) );
if (empty($search)) {
$search = get_posts( array(
'meta_query' => array( array(
'key' => 'sku',
'value' => get_query_var('s'),
'compare' => 'LIKE'
) ),
'posts_per_page' => -1,
'fields' => 'ids'
) );
if (!empty($search)) {
$query->set('s', '');
$query->set('post__in', $search);
$query->set('post_type', 'post');
}
}
};
}
add_filter( 'pre_get_posts', 'custom_search_query');
Но в любом случае мы получаем (в случае измененном поиска) проблему, что мы не можем вывести get_search_query() (в заголовке: Результат поиска по «…»). Можно исправить это если изменить get_search_query() на $_GET[«s»]. Пример:
<?php printf( __( 'Результаты поиска: %s' ), '<span>«' . $_GET["s"] . '»</span>' ); ?>
Ещё более простой и правильный способ изменения поиска
function custom_search_query( $query ) {
if ( !is_admin() && $query->is_search ) {
remove_action( 'pre_get_posts', __FUNCTION__ ); // чтобы не было бесконечного цикла
$search = get_posts( array(
's' => get_query_var('s'),
'posts_per_page' => -1,
'fields' => 'ids',
'post_type' => 'post',
'category__not_in' => array(1, 35, 4, 59, 269)
) );
if (empty($search)){
$query->set('meta_query', array(
array(
'key' => 'sku',
'value' => get_query_var('s'),
'compare' => 'LIKE'
)
));
$query->set('s', ''); // обнуляем основной поиск, !обязательно в конце, т.к. мы его используем в meta_query
}
$query->set('category__not_in',array(1, 35, 4, 59, 269));
$query->set('post_type', 'post');
return $query;
};
}
add_filter( 'pre_get_posts', 'custom_search_query');
[site-socialshare]