WP_Query — это мощный класс WordPress для выборки записей из базы данных. Однако стандартные параметры часто не покрывают все потребности при реализации сложного поиска и фильтрации контента. В этой статье мы разберём, как максимально эффективно использовать фильтры WP_Query для создания комплексного поиска с сортировкой, фильтрацией по мета-полям и таксономиям, а также по ключевым словам.
Основы работы с WP_Query и параметры фильтрации
Для начала рассмотрим, как формируется простой запрос с WP_Query. Пример базового запроса, который выбирает 10 последних записей типа 'post':
$args = [
'post_type' => 'post',
'posts_per_page' => 10
];
$query = new WP_Query($args);Этот запрос можно расширять с помощью параметров 'meta_query', 'tax_query' и других, чтобы фильтровать записи по произвольным полям и таксономиям.
Пример фильтрации по мета-полю 'price' больше 1000:
$args = [
'post_type' => 'product',
'meta_query' => [
[
'key' => 'price',
'value' => 1000,
'compare' => '>',
'type' => 'NUMERIC'
]
]
];
$query = new WP_Query($args);Таким образом можно комбинировать несколько условий через массивы.
Использование meta_query и tax_query для сложной фильтрации
Для комплексного поиска часто нужно фильтровать записи сразу по нескольким мета-полям и таксономиям. Для этого WP_Query поддерживает массивы с несколькими условиями и логическими операторами.
Пример: поиск товаров, где цена от 1000 до 5000 и категория 'gadgets' или 'accessories':
$args = [
'post_type' => 'product',
'meta_query' => [
'relation' => 'AND',
[
'key' => 'price',
'value' => [1000, 5000],
'compare' => 'BETWEEN',
'type' => 'NUMERIC'
]
],
'tax_query' => [
[
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => ['gadgets', 'accessories'],
'operator' => 'IN'
]
]
];
$query = new WP_Query($args);Здесь 'relation' => 'AND' говорит, что все условия в meta_query должны быть выполнены, а в tax_query — достаточно, чтобы таксономия была одной из указанных.
Чтобы объединить meta_query и tax_query логически, их WP_Query объединяет с оператором AND по умолчанию.
Добавление поиска по ключевым словам с кастомизацией запроса
Поиск по ключевым словам в WP_Query реализуется через параметр s. Но он ограничен стандартным поиском по заголовкам и содержимому. Чтобы расширить поиск на кастомные поля и таксономии, нужно использовать фильтр posts_search и/или posts_join.
Ниже пример функции, которая добавляет поиск по произвольному полю 'custom_field' вместе с содержимым:
function wplessons_posts_search_filter($search, $query) {
global $wpdb;
if (!$query->is_search() || !$query->is_main_query()) {
return $search;
}
$search_term = esc_sql($query->get('s'));
if (empty($search_term)) {
return $search;
}
// Расширяем поиск по произвольному полю
$search = " AND ( (" . $wpdb->posts . ".post_title LIKE '%" . $search_term . "%' ) OR (" . $wpdb->posts . ".post_content LIKE '%" . $search_term . "%' ) OR EXISTS (
SELECT 1 FROM " . $wpdb->postmeta . " pm
WHERE pm.post_id = " . $wpdb->posts . ".ID
AND pm.meta_key = 'custom_field'
AND pm.meta_value LIKE '%" . $search_term . "%'
)) ";
return $search;
}
add_filter('posts_search', 'wplessons_posts_search_filter', 10, 2);Эта функция расширяет стандартный поиск, добавляя проверку поля 'custom_field'. Такой подход позволяет пользователям искать записи по дополнительным параметрам.
Оптимизация и пагинация сложных запросов WP_Query
Сложные запросы с большим числом условий могут значительно нагрузить базу данных. Чтобы избежать тормозов и падений, нужно учитывать несколько моментов:
- Используйте индексы по мета-полям и таксономиям, если это возможно.
- Старайтесь избегать операторов LIKE с ведущим символом '%', так как они не используют индексы.
- Ограничивайте количество возвращаемых записей с помощью
posts_per_page. - Используйте кэширование результатов запросов через Transients API или плагины кеширования.
Пагинация стандартно работает с WP_Query через параметры paged и posts_per_page. Пример реализации пагинации на фронтенде:
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args['paged'] = $paged;
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
// вывод записи
}
echo paginate_links([
'total' => $query->max_num_pages
]);
}
wp_reset_postdata();Пример комплексного поиска с AJAX и WP_Query
Для улучшения UX хорошо использовать AJAX, чтобы пользователи могли видеть результаты поиска и фильтрации без перезагрузки страницы. Рассмотрим упрощённый пример, как реализовать AJAX-запрос с использованием WP_Query.
JS (jQuery) для отправки запроса:
jQuery(document).ready(function($) {
$('#search-form').on('submit', function(e) {
e.preventDefault();
var searchData = {
action: 'wplessons_ajax_search',
s: $('#search-input').val(),
category: $('#category-select').val()
};
$.post(wplessons_ajax_object.ajax_url, searchData, function(response) {
$('#search-results').html(response);
});
});
});PHP для обработки AJAX:
function wplessons_ajax_search() {
$s = sanitize_text_field($_POST['s']);
$category = sanitize_text_field($_POST['category']);
$args = [
'post_type' => 'post',
's' => $s,
'posts_per_page' => 10
];
if ($category) {
$args['tax_query'] = [[
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $category
]];
}
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<h3>' . get_the_title() . '</h3>';
echo '<p>' . get_the_excerpt() . '</p>';
}
} else {
echo '<p>Результаты не найдены.</p>';
}
wp_die();
}
add_action('wp_ajax_wplessons_ajax_search', 'wplessons_ajax_search');
add_action('wp_ajax_nopriv_wplessons_ajax_search', 'wplessons_ajax_search');Вместе с локализацией скрипта через wp_localize_script и передачей URL для AJAX это позволяет создать удобный интерфейс поиска по сайту.
Рекомендации по плагинам для расширения возможностей поиска и фильтрации
Если хочется использовать готовые решения, можно обратить внимание на следующие плагины, которые хорошо интегрируются с WP_Query и расширяют функционал фильтрации:
- ABC Pagination — расширенная пагинация с AJAX и кастомными стилями.
- WPRemark — комментарии с возможностью фильтрации и сортировки.
- Quizle — для интерактивных опросов и тестов, которые можно использовать для дополнительной фильтрации.
Эти плагины можно использовать для создания сложных интерфейсов поиска и фильтров без глубокого погружения в код.