Одной из частых задач при разработке на WordPress является необходимость фильтровать записи по значениям метаданных (custom fields). Это особенно актуально для сайтов с большим количеством кастомного контента, где нужно вывести только те записи, которые соответствуют определённым критериям, записанным в метаданных.
Что такое метаданные в WordPress и зачем их фильтровать
Метаданные — это дополнительная информация, связанная с постами, страницами или другими типами записей в WordPress. Они хранятся в таблице wp_postmeta и позволяют расширять функциональность сайта, например, указывать цену товара, дату события, рейтинг и многое другое.
Фильтрация по метаданным позволяет создавать сложные выборки, которые невозможно получить только с помощью стандартных категорий или тегов. Например, можно вывести все товары с ценой меньше 1000 рублей, или все статьи, где рейтинг выше 4.
Использование WP_Query для фильтрации по метаданным
Самый удобный способ фильтрации — использовать класс WP_Query с параметром meta_query. Это массив условий, который задаёт правила фильтрации по метаданным.
Пример запроса для выборки постов, где метаполе price меньше 1000:
$args = [
'post_type' => 'product',
'meta_query' => [
[
'key' => 'price',
'value' => 1000,
'compare' => '<',
'type' => 'NUMERIC'
]
]
];
$query = new WP_Query($args);Обратите внимание на параметр type, который определяет тип данных в метаполе — очень важно для корректного сравнения чисел или дат.
Сложные условия с несколькими метаполями
Можно комбинировать несколько условий с помощью параметра relation («AND» или «OR»):
$args = [
'post_type' => 'product',
'meta_query' => [
'relation' => 'AND',
[
'key' => 'price',
'value' => 1000,
'compare' => '<',
'type' => 'NUMERIC'
],
[
'key' => 'in_stock',
'value' => 'yes',
'compare' => '='
]
]
];
$query = new WP_Query($args);Это позволит вывести товары, которые есть в наличии и стоят меньше 1000.
Оптимизация запросов с метаданными
Запросы с meta_query могут замедлять сайт при большом объёме данных. Рекомендуется:
- Добавлять индексы в таблицу
wp_postmetaпо колонкамmeta_keyиmeta_value. - Минимизировать количество условий в
meta_query. - Использовать кэширование — например, плагин Clearfy Pro умеет оптимизировать такие запросы.
Пример пользовательской функции для упрощения фильтрации по метаданным
Чтобы облегчить повторное использование фильтрации, создадим функцию wpcompany_get_posts_by_meta:
function wpcompany_get_posts_by_meta($post_type, $meta_conditions, $relation = 'AND', $posts_per_page = 10) {
$args = [
'post_type' => $post_type,
'posts_per_page' => $posts_per_page,
'meta_query' => [
'relation' => $relation,
]
];
foreach ($meta_conditions as $condition) {
$args['meta_query'][] = $condition;
}
return new WP_Query($args);
}
// Пример использования
$conditions = [
[
'key' => 'price',
'value' => 500,
'compare' => '<=',
'type' => 'NUMERIC'
],
[
'key' => 'color',
'value' => 'red',
'compare' => '='
]
];
$query = wpcompany_get_posts_by_meta('product', $conditions);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<h3>' . get_the_title() . '</h3>';
}
wp_reset_postdata();
}Использование плагинов для расширенного фильтра
Если не хочется писать код, можно использовать готовые решения. Например:
- Clearfy Pro — плагин для оптимизации и расширения функционала, включая фильтры по метаданным.
- WPRemark — плагин для отзывов и рейтингов с возможностью фильтрации по параметрам.
Оба плагина интегрируются с кастомными типами записей и метаданными, что значительно упрощает настройку фильтров для конечного пользователя.
Фильтрация через REST API
Для сайтов с фронтендом на React, Vue или мобильных приложений удобно фильтровать данные через REST API WordPress. Для этого можно расширить стандартный эндпоинт, добавив поддержку параметров meta_key и meta_value.
add_action('rest_api_init', function () {
register_rest_route('wp/v2', '/products/', [
'methods' => 'GET',
'callback' => 'wpcompany_rest_filter_products',
]);
});
function wpcompany_rest_filter_products(WP_REST_Request $request) {
$meta_key = $request->get_param('meta_key');
$meta_value = $request->get_param('meta_value');
$args = [
'post_type' => 'product',
'posts_per_page' => 10
];
if ($meta_key && $meta_value) {
$args['meta_query'] = [[
'key' => $meta_key,
'value' => $meta_value,
'compare' => '='
]];
}
$query = new WP_Query($args);
$posts = [];
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$posts[] = [
'id' => get_the_ID(),
'title' => get_the_title(),
'link' => get_permalink()
];
}
wp_reset_postdata();
}
return rest_ensure_response($posts);
}Теперь можно делать запросы типа /wp-json/wp/v2/products?meta_key=price&meta_value=500 и получать отфильтрованный список.