Фильтрация постов по пользовательским полям (метаданным) в WordPress — одна из самых востребованных задач при разработке сайтов с кастомным контентом. Для этого используется параметр meta_query в WP_Query, который позволяет задавать сложные условия выборки. В этой статье разберём, как правильно строить мета-запросы, какие операторы доступны, и как повысить производительность запросов.
Что такое meta_query и зачем он нужен
В WordPress каждый пост может иметь дополнительные данные — метаданные, которые хранятся в таблице wp_postmeta. Это могут быть цены, даты, статусы, ID связанных объектов и многое другое. Параметр meta_query служит для построения SQL-запросов по этим метаданным.
Например, если у вас есть интернет-магазин на WordPress и вы хотите вывести товары с ценой от 1000 рублей, то meta_query позволит это сделать без сложных запросов к базе.
Использование мета-запросов позволяет создавать гибкие фильтры, которые работают по нескольким полям одновременно, с логическими операторами AND, OR и даже вложенными условиями.
Синтаксис meta_query: базовые примеры
Основной формат meta_query — это массив массивов, в котором каждый вложенный массив задаёт одно условие по метаданным.
$args = [
'post_type' => 'product',
'meta_query' => [
[
'key' => 'price',
'value' => 1000,
'type' => 'NUMERIC',
'compare' => '>='
]
]
];
$query = new WP_Query($args);Здесь мы выбираем все посты типа product, у которых мета-ключ price больше или равен 1000. Обратите внимание, что type указывает тип данных, чтобы сравнение было корректным (числовое, строковое, дата и т.д.).
Основные параметры условия meta_query
- key — имя метаполя;
- value — значение для сравнения;
- compare — оператор сравнения ('=', '!=', '>', '<', '>=', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'EXISTS', 'NOT EXISTS');
- type — тип данных ('NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED').
Сложные фильтры с несколькими условиями и логикой
Если нужно фильтровать по нескольким метаполям, можно объединить условия в массив с ключом relation, который принимает значения 'AND' или 'OR'.
$args = [
'post_type' => 'product',
'meta_query' => [
'relation' => 'AND',
[
'key' => 'price',
'value' => [500, 2000],
'type' => 'NUMERIC',
'compare' => 'BETWEEN'
],
[
'key' => 'color',
'value' => ['red', 'blue'],
'compare' => 'IN'
]
]
];
$query = new WP_Query($args);В этом примере выбираются товары с ценой от 500 до 2000 и цветом 'red' или 'blue'. Такая связка условий очень удобна для сложных фильтров на сайтах с большим каталогом.
Вложенные meta_query
WordPress поддерживает и вложенные meta_query, что позволяет строить ещё более гибкие фильтры.
$args = [
'post_type' => 'product',
'meta_query' => [
'relation' => 'OR',
[
'relation' => 'AND',
[
'key' => 'price',
'value' => 1000,
'compare' => '>='
],
[
'key' => 'color',
'value' => 'red',
'compare' => '='
]
],
[
'key' => 'discount',
'value' => 0,
'compare' => '>'
]
]
];
$query = new WP_Query($args);Здесь выбираются посты, которые либо имеют цену от 1000 и красный цвет, либо имеют скидку больше нуля.
Оптимизация и кеширование meta_query
Важно помнить, что сложные meta_query могут негативно влиять на производительность, так как запросы включают JOIN с таблицей wp_postmeta, которая может быть очень большой.
Для улучшения скорости стоит:
- Добавлять индексы в базу данных на мета-ключи, по которым часто идут запросы.
- Использовать плагин Clearfy Pro для оптимизации базы и кеширования.
- Кэшировать результаты запросов с помощью Transients API или внешних кешей.
Пример функции с префиксом wppartner, возвращающей отфильтрованные посты
function wppartner_get_filtered_products($min_price, $colors) {
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'meta_query' => [
[
'key' => 'price',
'value' => $min_price,
'type' => 'NUMERIC',
'compare' => '>='
],
[
'key' => 'color',
'value' => $colors,
'compare' => 'IN'
]
]
];
$query = new WP_Query($args);
return $query->posts;
}Эта функция принимает минимальную цену и массив цветов, возвращая все товары, которые соответствуют критериям. Такой подход упрощает многократное использование фильтра в разных частях сайта.
Использование фильтра в шаблоне с пагинацией
Чтобы вывести посты с фильтрацией и пагинацией, можно использовать следующий пример:
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = [
'post_type' => 'product',
'posts_per_page' => 10,
'paged' => $paged,
'meta_query' => [
[
'key' => 'price',
'value' => 1000,
'type' => 'NUMERIC',
'compare' => '>='
]
]
];
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
the_title('<h3>', '</h3>');
// вывод остального контента
}
// пагинация
echo paginate_links([
'total' => $query->max_num_pages
]);
}
wp_reset_postdata();Это базовый пример, который можно расширять и адаптировать под конкретные задачи.
Выводы и рекомендации
Использование meta_query — мощный инструмент, но требует аккуратности и тестирования. Важно:
- Чётко определять типы метаданных и операторы.
- Минимизировать количество JOIN в запросах.
- Использовать индексы и кеширование.
- Тестировать производительность на реальных данных.
Для комплексных проектов рекомендуем обратить внимание на плагины оптимизации и кеширования, например, Clearfy Pro, а также на расширения для создания пользовательских фильтров.