Введение в фильтрацию по пользовательским метаданным
Фильтрация записей по пользовательским метаданным (custom fields) — важный инструмент для улучшения навигации по сайту и повышения удобства пользователей. Особенно это актуально для сайтов с большим количеством контента, где стандартные категории и метки не всегда позволяют быстро найти нужную информацию.
В этой статье разберём, как создать гибкий и динамичный фильтр по метаданным в WordPress, используя WP_Query с параметрами метазапросов (meta_query). Также рассмотрим, как реализовать интерфейс фильтра с помощью формы и как интегрировать это с плагинами для повышения функциональности.
Подготовка: регистрация пользовательских метаданных
Для начала убедимся, что у вас есть записи с пользовательскими метаданными. Допустим, у нас есть тип записи product, и в нем есть мета-поля price, color и in_stock.
Добавлять метаданные можно через админку вручную или программно при сохранении записи. Вот пример функции из темы или плагина, которая добавляет мета-поля:
function wppartner_save_product_meta($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
if (isset($_POST['wppartner_price'])) {
update_post_meta($post_id, 'price', sanitize_text_field($_POST['wppartner_price']));
}
if (isset($_POST['wppartner_color'])) {
update_post_meta($post_id, 'color', sanitize_text_field($_POST['wppartner_color']));
}
if (isset($_POST['wppartner_in_stock'])) {
update_post_meta($post_id, 'in_stock', $_POST['wppartner_in_stock'] ? 'yes' : 'no');
}
}
add_action('save_post_product', 'wppartner_save_product_meta');Эта функция обрабатывает сохранение данных при редактировании записи в админке.
Создание формы фильтрации по метаданным
Теперь создадим форму на фронтенде, которая позволит пользователям выбирать параметры фильтрации. Например, фильтр по цене, цвету и наличию на складе.
Форма может выглядеть так:
<form method="GET" action="">
<label for="price_min">Цена от:</label>
<input type="number" name="price_min" id="price_min" value="<?php echo esc_attr($_GET['price_min'] ?? ''); ?>">
<label for="price_max">Цена до:</label>
<input type="number" name="price_max" id="price_max" value="<?php echo esc_attr($_GET['price_max'] ?? ''); ?>">
<label for="color">Цвет:</label>
<select name="color" id="color">
<option value="">Любой</option>
<option value="red" <?php selected($_GET['color'] ?? '', 'red'); ?>>Красный</option>
<option value="blue" <?php selected($_GET['color'] ?? '', 'blue'); ?>>Синий</option>
<option value="green" <?php selected($_GET['color'] ?? '', 'green'); ?>>Зелёный</option>
</select>
<label><input type="checkbox" name="in_stock" value="1" <?php checked(isset($_GET['in_stock'])); ?>> В наличии</label>
<button type="submit">Фильтровать</button>
</form>Эта форма отправляет GET-запрос с параметрами фильтрации, которые мы используем далее для настройки запроса WP_Query.
Настройка WP_Query с meta_query для динамичного фильтра
Основная магия фильтра — настройка аргументов для WP_Query. Рассмотрим пример функции, которая собирает параметры из GET и формирует запрос:
function wppartner_get_filtered_products() {
$meta_query = ['relation' => 'AND'];
if (!empty($_GET['price_min'])) {
$meta_query[] = [
'key' => 'price',
'value' => intval($_GET['price_min']),
'type' => 'NUMERIC',
'compare' => '>='
];
}
if (!empty($_GET['price_max'])) {
$meta_query[] = [
'key' => 'price',
'value' => intval($_GET['price_max']),
'type' => 'NUMERIC',
'compare' => '<='
];
}
if (!empty($_GET['color'])) {
$meta_query[] = [
'key' => 'color',
'value' => sanitize_text_field($_GET['color']),
'compare' => '='
];
}
if (!empty($_GET['in_stock'])) {
$meta_query[] = [
'key' => 'in_stock',
'value' => 'yes',
'compare' => '='
];
}
$args = [
'post_type' => 'product',
'posts_per_page' => 10,
'meta_query' => $meta_query
];
$query = new WP_Query($args);
return $query;
}Эта функция формирует запрос с учетом выбранных пользователем фильтров и возвращает объект WP_Query с подходящими постами.
Вывод результатов фильтрации
Чтобы вывести результаты, вызовите функцию и пройдитесь по постам:
$query = wppartner_get_filtered_products();
if ($query->have_posts()) {
echo '<ul>';
while ($query->have_posts()) {
$query->the_post();
echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
}
echo '</ul>';
wp_reset_postdata();
} else {
echo '<p>По вашему запросу ничего не найдено.</p>';
}Так пользователь увидит отфильтрованные записи с учётом заданных параметров.
Рекомендации по плагинам для расширения возможностей фильтрации
Если хочется получить более продвинутый функционал с минимальными усилиями, можно использовать готовые решения:
- FacetWP — мощный плагин для создания фильтров с ajax-подгрузкой и множественными условиями.
- Filter Everything — бесплатный и удобный плагин для фильтрации по метаданным, таксономиям и другим параметрам.
- Clearfy Pro — оптимизационный плагин, который также помогает улучшить производительность фильтров и запросов.
Для интеграции с этими плагинами достаточно зарегистрировать свои метаданные и типы записей, а затем настроить фильтры через интерфейс плагина.
Подсказки по производительности и отладке
Фильтрация по метаданным может создавать нагрузку на базу данных, особенно при большом количестве записей. Вот несколько советов по оптимизации:
- Используйте индексы для метаполей, если возможно (на уровне базы данных).
- Ограничивайте количество постов на странице.
- Кэшируйте результаты запросов с помощью Transients API или плагинов кэширования.
- Профилируйте запросы с помощью Query Monitor для выявления проблем.
Если фильтр не работает как ожидалось, проверьте правильность названий метаполей и типы сравнения в meta_query.