В современных проектах на WordPress часто возникает необходимость реализовать удобную систему фильтрации записей. Особенно это актуально для сайтов с большим количеством контента — каталогов, блогов, магазинов и портфолио. В этой статье мы подробно рассмотрим, как создать динамические фильтры по категориям и метаполям без использования громоздких конструкторов, только с помощью кода и штатных возможностей WordPress.
Почему нужны динамические фильтры и какие задачи они решают
Статичные фильтры, сделанные вручную, быстро устаревают и требуют постоянного обновления при добавлении новых категорий или свойств записей. Динамические фильтры автоматически подтягивают актуальные значения таксономий и метаданных, что значительно облегчает администрирование и улучшает пользовательский опыт.
Основные преимущества динамических фильтров:
- Актуальность — всегда показывают доступные для фильтрации значения;
- Гибкость — с их помощью можно комбинировать фильтрацию по разным параметрам;
- Производительность — фильтрация происходит на уровне запросов WP_Query;
- Удобство в управлении — не нужно вручную обновлять список фильтров.
Динамические фильтры по категориям: базовая реализация
Начнем с самого распространенного варианта — фильтрация по категориям записей. Предположим, у нас есть блог, и мы хотим вывести список категорий в виде чекбоксов, позволяющих показать записи из выбранных категорий.
Для вывода списка категорий используем функцию get_categories():
function wpkpi_get_category_filters() {
$categories = get_categories([ 'hide_empty' => true ]);
echo '<form method="GET" id="wpkpi_cat_filter">';
foreach ($categories as $category) {
$checked = (isset($_GET['wpkpi_cat']) && in_array($category->term_id, $_GET['wpkpi_cat'])) ? 'checked' : '';
echo '<label><input type="checkbox" name="wpkpi_cat[]" value="'. esc_attr($category->term_id) .'" '. $checked .'> ' . esc_html($category->name) . '</label><br>';
}
echo '<button type="submit">Фильтровать</button>';
echo '</form>';
}Этот код выведет форму с чекбоксами для всех категорий, которые содержат записи. Пользователь может выбрать несколько категорий и отправить форму.
Обработка выбранных категорий в запросе WP_Query
Теперь нужно отфильтровать записи по выбранным категориям. Для этого модифицируем WP_Query, используя параметр category__in:
function wpkpi_filter_posts_by_category() {
$args = [
'post_type' => 'post',
'posts_per_page' => 10,
];
if (isset($_GET['wpkpi_cat']) && !empty($_GET['wpkpi_cat'])) {
$cat_ids = array_map('intval', $_GET['wpkpi_cat']);
$args['category__in'] = $cat_ids;
}
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<h3><a href="' . get_permalink() . '">' . get_the_title() . '</a></h3>';
}
} else {
echo '<p>Записи не найдены.</p>';
}
wp_reset_postdata();
}Чтобы выводить форму и результаты на одной странице, в шаблоне вызывайте сначала wpkpi_get_category_filters(), затем wpkpi_filter_posts_by_category().
Фильтрация по метаполям: пример с числовым фильтром
Категории — это один из вариантов таксономий, а часто нужно фильтровать записи по произвольным полям (метаполям). Например, если у вас каталог товаров с метаполем price, можно сделать фильтр по диапазону цен.
Рассмотрим пример с фильтрацией по минимальной и максимальной цене.
Вывод формы для фильтрации по диапазону цен
function wpkpi_price_filter_form() {
$min_price = isset($_GET['wpkpi_min_price']) ? intval($_GET['wpkpi_min_price']) : '';
$max_price = isset($_GET['wpkpi_max_price']) ? intval($_GET['wpkpi_max_price']) : '';
echo '<form method="GET" id="wpkpi_price_filter">';
echo '<label>Минимальная цена: <input type="number" name="wpkpi_min_price" value="' . esc_attr($min_price) . '"></label><br>';
echo '<label>Максимальная цена: <input type="number" name="wpkpi_max_price" value="' . esc_attr($max_price) . '"></label><br>';
echo '<button type="submit">Фильтровать</button>';
echo '</form>';
}Обработка фильтра по цене в WP_Query
Чтобы ограничить выборку по метаполю, используем параметр meta_query:
function wpkpi_filter_posts_by_price() {
$args = [
'post_type' => 'product',
'posts_per_page' => 10,
];
$meta_query = [];
if (isset($_GET['wpkpi_min_price']) && $_GET['wpkpi_min_price'] !== '') {
$meta_query[] = [
'key' => 'price',
'value' => intval($_GET['wpkpi_min_price']),
'type' => 'NUMERIC',
'compare' => '>='
];
}
if (isset($_GET['wpkpi_max_price']) && $_GET['wpkpi_max_price'] !== '') {
$meta_query[] = [
'key' => 'price',
'value' => intval($_GET['wpkpi_max_price']),
'type' => 'NUMERIC',
'compare' => '<='
];
}
if (!empty($meta_query)) {
$args['meta_query'] = $meta_query;
}
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<h3><a href="' . get_permalink() . '">' . get_the_title() . '</a> — Цена: ' . esc_html(get_post_meta(get_the_ID(), 'price', true)) . '</h3>';
}
} else {
echo '<p>Товары не найдены по заданным параметрам.</p>';
}
wp_reset_postdata();
}Комбинирование фильтров по категориям и метаполям
На практике часто требуется комбинировать нескольких фильтров, например, категории и диапазон цен одновременно. Для этого объединяем параметры в один запрос WP_Query.
Пример комбинированной фильтрации:
function wpkpi_combined_filter() {
$args = [
'post_type' => 'product',
'posts_per_page' => 10,
];
// Категории
if (isset($_GET['wpkpi_cat']) && !empty($_GET['wpkpi_cat'])) {
$cat_ids = array_map('intval', $_GET['wpkpi_cat']);
$args['tax_query'] = [
[
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => $cat_ids,
'operator' => 'IN'
]
];
}
// Метаполя
$meta_query = [];
if (isset($_GET['wpkpi_min_price']) && $_GET['wpkpi_min_price'] !== '') {
$meta_query[] = [
'key' => 'price',
'value' => intval($_GET['wpkpi_min_price']),
'type' => 'NUMERIC',
'compare' => '>='
];
}
if (isset($_GET['wpkpi_max_price']) && $_GET['wpkpi_max_price'] !== '') {
$meta_query[] = [
'key' => 'price',
'value' => intval($_GET['wpkpi_max_price']),
'type' => 'NUMERIC',
'compare' => '<='
];
}
if (!empty($meta_query)) {
$args['meta_query'] = $meta_query;
}
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<h3><a href="' . get_permalink() . '">' . get_the_title() . '</a> — Цена: ' . esc_html(get_post_meta(get_the_ID(), 'price', true)) . '</h3>';
}
} else {
echo '<p>По заданным фильтрам ничего не найдено.</p>';
}
wp_reset_postdata();
}Для удобства выводите формы фильтров (категории и цена) на одной странице и вызывайте эту функцию для показа результата.
Лучшие плагины для расширения функционала фильтров в WordPress
Если хочется упростить задачу и получить более мощный интерфейс, можно использовать плагины. Вот несколько рекомендованных:
- Clearfy Pro — оптимизация и расширение возможностей WordPress, в том числе улучшение фильтров и запросов;
- WPRemark — мощный конструктор отзывов и рейтингов с поддержкой фильтрации;
- ABC Pagination — улучшенная пагинация для больших выборок с фильтрами.
Однако даже с этими плагинами полезно понимать, как работают базовые механизмы фильтрации, чтобы гибко настраивать сайт под любые задачи.
Советы по оптимизации и производительности фильтров
При добавлении фильтров важно учитывать производительность:
- Используйте индексированные поля и таксономии, а не только метаполя;
- Кэшируйте результаты запросов с помощью Transients API или внешних кешей;
- Ограничивайте количество возвращаемых записей и используйте пагинацию;
- Избегайте сложных вложенных
meta_queryбез необходимости.
Правильное построение запросов и грамотное кеширование обеспечат быструю работу фильтров даже на больших сайтах.