Как сделать вывод списка постов с фильтрацией по категории и мету в WordPress

В этой статье разберём, как вывести на страницу WordPress список постов с возможностью фильтрации по категориям и мета-полям. Это частая задача при создании кастомных архивов, каталогов или каталогов товаров на базе WordPress. Мы рассмотрим практическое решение с примерами кода, чтобы вы могли быстро внедрить фильтрацию на своём сайте.

Зачем нужна фильтрация по категориям и мета-полям

Категории позволяют сгруппировать записи по темам, а мета-поля (custom fields) — хранить дополнительную информацию, например, цену, цвет, рейтинг и другое. Объединённая фильтрация помогает пользователям быстрее находить нужный контент.

Например, если у вас каталог товаров, можно показывать только товары из категории "Футболки" и с мета-полем "цвет" = "синий".

Используем класс WP_Query для выборки с фильтрацией

Основной инструмент для выборки записей — класс WP_Query. Для фильтрации по категориям применяется параметр category_name или tax_query, для мета-полей — meta_query.

Пример базового запроса с фильтрацией по категории и мета-полю:

function wpapp_get_filtered_posts($category_slug, $meta_key, $meta_value) {
    $args = [
        'post_type' => 'post',
        'category_name' => $category_slug,
        'meta_query' => [
            [
                'key' => $meta_key,
                'value' => $meta_value,
                'compare' => '='
            ]
        ]
    ];
    $query = new WP_Query($args);
    return $query;
}

Здесь мы создаём функцию wpapp_get_filtered_posts, которая принимает слаг категории, ключ и значение мета-поля, и возвращает объект WP_Query с подходящими постами.

Выводим список постов и добавляем HTML для фильтров

Чтобы пользователь мог выбрать категорию и значение мета-поля, необходимо добавить форму фильтрации. Рассмотрим пример с выпадающими списками:

<form method="GET">
  <select name="category">
    <option value="">Выберите категорию</option>
    <?php
    $categories = get_categories();
    foreach ($categories as $cat) {
        $selected = (isset($_GET['category']) && $_GET['category'] === $cat->slug) ? 'selected' : '';
        echo "<option value=\"{$cat->slug}\" $selected>{$cat->name}</option>";
    }
    ?>
  </select>

  <select name="color">
    <option value="">Выберите цвет</option>
    <option value="red">Красный</option>
    <option value="blue">Синий</option>
    <option value="green">Зелёный</option>
  </select>

  <button type="submit">Фильтровать</button>
</form>

При отправке формы параметры будут доступны в $_GET. Теперь подключим фильтрацию к нашему запросу:

$category = isset($_GET['category']) ? sanitize_text_field($_GET['category']) : '';
$color = isset($_GET['color']) ? sanitize_text_field($_GET['color']) : '';

$args = [
    'post_type' => 'post',
    'posts_per_page' => 10,
];

if ($category) {
    $args['category_name'] = $category;
}

if ($color) {
    $args['meta_query'] = [
        [
            'key' => 'color',
            'value' => $color,
            'compare' => '=',
        ]
    ];
}

$query = new WP_Query($args);

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>';
} else {
    echo '<p>Посты не найдены</p>';
}
wp_reset_postdata();

Расширенные возможности: фильтрация нескольких мета полей и AJAX

Фильтрация по нескольким мета-полям

Если нужно фильтровать сразу по нескольким мета-полям, используйте массив в meta_query с параметром relation:

$args['meta_query'] = [
    'relation' => 'AND',
    [
        'key' => 'color',
        'value' => $color,
        'compare' => '=',
    ],
    [
        'key' => 'size',
        'value' => $size,
        'compare' => '=',
    ]
];

Так вы сможете фильтровать, например, по цвету и размеру одновременно.

Добавляем AJAX фильтрацию без перезагрузки

Для улучшения UX можно сделать фильтрацию через AJAX. Это уменьшит время загрузки и сделает интерфейс живым.

Основные шаги:

  • Создайте JS скрипт, который будет слушать изменения фильтров и отправлять AJAX запрос на сервер.
  • Регистрируйте обработчик AJAX в WordPress через add_action('wp_ajax_...') и add_action('wp_ajax_nopriv_...').
  • Обрабатывайте параметры, формируйте WP_Query и возвращайте HTML с постами.
  • В JS вставляйте полученный HTML в нужный блок.

Пример JS (jQuery):

jQuery(document).ready(function($) {
    $('#filter-form select').on('change', function() {
        var data = {
            action: 'wpapp_filter_posts',
            category: $('#filter-category').val(),
            color: $('#filter-color').val(),
        };

        $.post(wpapp_ajax_object.ajax_url, data, function(response) {
            $('#posts-container').html(response);
        });
    });
});

PHP обработчик:

add_action('wp_ajax_wpapp_filter_posts', 'wpapp_ajax_filter_posts');
add_action('wp_ajax_nopriv_wpapp_filter_posts', 'wpapp_ajax_filter_posts');

function wpapp_ajax_filter_posts() {
    $category = isset($_POST['category']) ? sanitize_text_field($_POST['category']) : '';
    $color = isset($_POST['color']) ? sanitize_text_field($_POST['color']) : '';

    $args = [
        'post_type' => 'post',
        'posts_per_page' => 10,
    ];

    if ($category) {
        $args['category_name'] = $category;
    }

    if ($color) {
        $args['meta_query'] = [
            [
                'key' => 'color',
                'value' => $color,
                'compare' => '=',
            ]
        ];
    }

    $query = new WP_Query($args);

    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>';
    } else {
        echo '<p>Посты не найдены</p>';
    }
    wp_reset_postdata();
    wp_die();
}

Не забудьте локализовать скрипт, чтобы передать ajax_url:

wp_enqueue_script('wpapp-filter', get_template_directory_uri() . '/js/filter.js', ['jquery'], null, true);
wp_localize_script('wpapp-filter', 'wpapp_ajax_object', [
    'ajax_url' => admin_url('admin-ajax.php'),
]);

Использование готовых плагинов для расширенной фильтрации

Если не хочется писать код самостоятельно, можно использовать плагины:

  • Clearfy Pro — расширяет стандартные функции WordPress, в том числе улучшает работу с запросами и фильтрацией.
  • Плагин FacetWP — мощный инструмент для создания AJAX-фильтров по таксономиям и мета-полям.
  • Плагин Search & Filter — простой в использовании фильтр с настройками для категорий и кастомных полей.

Для интеграции с WPShop и дополнительной кастомизации рекомендуем посмотреть официальный сайт WPShop.

Выводы и рекомендации

Фильтрация постов по категориям и мета-полям — важный инструмент для удобства пользователей и повышения конверсии. Для простых задач достаточно WP_Query с параметрами category_name и meta_query. Для более сложных — стоит использовать AJAX и готовые плагины.

Обязательно фильтруйте и валидируйте входящие данные, чтобы избежать ошибок и уязвимостей.

Наш каталог плагинов WordPress