Как создать динамические фильтры в теме WordPress для кастомных типов записей

Зачем нужны динамические фильтры в теме WordPress

Если вы работаете с кастомными типами записей (Custom Post Types, CPT) в WordPress, часто возникает задача предоставить пользователю удобный способ отфильтровать записи по определённым параметрам: таксономиям, метаполям, датам и другим атрибутам. Это особенно актуально для тем, где контент разнообразен и должен быстро находиться посетителями.

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

Подготовка: регистрация кастомного типа записей и таксономий

Для начала предположим, что у вас есть кастомный тип записей portfolio и две таксономии: project_type (тип проекта) и technology (технология). Если вы еще не зарегистрировали их, вот пример регистрации в файле functions.php вашей темы:

function wp_theme_register_cpt_and_taxonomies() {
    // Регистрируем кастомный тип записей
    register_post_type('portfolio', [
        'labels' => [
            'name' => 'Портфолио',
            'singular_name' => 'Проект',
        ],
        'public' => true,
        'has_archive' => true,
        'rewrite' => ['slug' => 'portfolio'],
        'supports' => ['title', 'editor', 'thumbnail'],
        'show_in_rest' => true // для поддержки Gutenberg
    ]);

    // Регистрируем таксономию project_type
    register_taxonomy('project_type', 'portfolio', [
        'labels' => [
            'name' => 'Типы проектов',
            'singular_name' => 'Тип проекта',
        ],
        'hierarchical' => true,
        'show_in_rest' => true,
        'rewrite' => ['slug' => 'project-type']
    ]);

    // Регистрируем таксономию technology
    register_taxonomy('technology', 'portfolio', [
        'labels' => [
            'name' => 'Технологии',
            'singular_name' => 'Технология',
        ],
        'hierarchical' => false,
        'show_in_rest' => true,
        'rewrite' => ['slug' => 'technology']
    ]);
}
add_action('init', 'wp_theme_register_cpt_and_taxonomies');

Этот код гарантирует, что у вас есть все необходимое для фильтрации по таксономиям.

Создание формы динамических фильтров в шаблоне темы

Далее создадим форму, которая выведет все доступные термины таксономий для выбора пользователем. Для удобства реализуем это в файле шаблона, например, archive-portfolio.php или отдельном шаблоне страницы.

Пример формы с фильтрами:

<form method="GET" action="">
    <div class="filter-group">
        <label for="project_type">Тип проекта:</label>
        <select name="project_type" id="project_type">
            <option value="">Все</option>
            <?php
            $project_types = get_terms(['taxonomy' => 'project_type', 'hide_empty' => true]);
            foreach ($project_types as $term) {
                $selected = (isset($_GET['project_type']) && $_GET['project_type'] === $term->slug) ? 'selected' : '';
                echo "<option value='{$term->slug}' $selected>{$term->name}</option>";
            }
            ?>
        </select>
    </div>

    <div class="filter-group">
        <label for="technology">Технология:</label>
        <select name="technology" id="technology">
            <option value="">Все</option>
            <?php
            $technologies = get_terms(['taxonomy' => 'technology', 'hide_empty' => true]);
            foreach ($technologies as $term) {
                $selected = (isset($_GET['technology']) && $_GET['technology'] === $term->slug) ? 'selected' : '';
                echo "<option value='{$term->slug}' $selected>{$term->name}</option>";
            }
            ?>
        </select>
    </div>

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

Здесь мы выводим два выпадающих списка, которые при отправке передают параметры в URL, например ?project_type=web&technology=php.

Обработка фильтров и вывод результатов

Чтобы фильтровать записи, нужно изменить запрос WordPress. Для этого в файле шаблона или через хуки (например, pre_get_posts) добавим логику для фильтрации.

Пример обработки в archive-portfolio.php:

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

// Массив для таксономий
$tax_query = [];

if (!empty($_GET['project_type'])) {
    $tax_query[] = [
        'taxonomy' => 'project_type',
        'field' => 'slug',
        'terms' => sanitize_text_field($_GET['project_type'])
    ];
}
if (!empty($_GET['technology'])) {
    $tax_query[] = [
        'taxonomy' => 'technology',
        'field' => 'slug',
        'terms' => sanitize_text_field($_GET['technology'])
    ];
}

if (!empty($tax_query)) {
    // Если несколько фильтров, объединяем логикой AND
    $args['tax_query'] = ['relation' => 'AND'] + $tax_query;
}

$query = new WP_Query($args);

if ($query->have_posts()) {
    while ($query->have_posts()) {
        $query->the_post();
        ?>
        <article id="post-<?php the_ID(); ?>" class="portfolio-item">
            <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
            <div class="entry-summary"><?php the_excerpt(); ?></div>
        </article>
        <?php
    }
    wp_reset_postdata();
} else {
    echo '<p>Проекты не найдены.</p>';
}

Этот код строит запрос с учетом выбранных фильтров и выводит результаты.

Добавление фильтра по метаполю с примером кода

Иногда нужно фильтровать записи не только по таксономиям, но и по метаполям (Custom Fields). Например, у вас есть метаполе project_budget и вы хотите отфильтровать проекты с бюджетом менее 100000.

Расширим логику запроса:

if (!empty($_GET['max_budget'])) {
    $max_budget = intval($_GET['max_budget']);
    $args['meta_query'][] = [
        'key' => 'project_budget',
        'value' => $max_budget,
        'type' => 'NUMERIC',
        'compare' => '<='
    ];
}

Добавим в форму соответствующее поле:

<div class="filter-group">
    <label for="max_budget">Максимальный бюджет:</label>
    <input type="number" name="max_budget" id="max_budget" value="<?php echo isset($_GET['max_budget']) ? intval($_GET['max_budget']) : ''; ?>" />
</div>

Теперь пользователь может фильтровать проекты и по бюджету, что расширяет возможности поиска.

Советы по оптимизации и UX для динамических фильтров

Фильтрация по нескольким параметрам может значительно увеличить нагрузку на базу данных, особенно если у вас большой каталог. Чтобы этого избежать:

  • Используйте индексацию метаполей в базе данных.
  • Кешируйте результаты с помощью Transients API или плагинов кеширования.
  • Добавьте AJAX-запросы для динамической подгрузки без перезагрузки страницы — это улучшит UX.
  • Используйте удобные UI-элементы: чекбоксы, слайдеры для числовых значений и автозаполнение для тегов.

Для реализации AJAX можно подключить скрипты и обработчики в теме, используя стандартные WordPress-хуки wp_ajax_ и wp_ajax_nopriv_. Это позволит динамически обновлять список проектов при смене фильтра.

Пример AJAX-фильтрации с использованием WP AJAX API

Добавим пример JS-кода для отправки данных фильтрации и обновления результатов:

jQuery(document).ready(function($) {
    $('#filter-form select, #filter-form input').on('change', function() {
        var data = $('#filter-form').serialize();
        $.ajax({
            url: wp_theme_ajax_object.ajax_url,
            type: 'GET',
            data: data + '&action=wp_theme_filter_portfolio',
            success: function(response) {
                $('#portfolio-results').html(response);
            }
        });
    });
});

И в functions.php добавим обработчик:

function wp_theme_filter_portfolio_callback() {
    $args = [
        'post_type' => 'portfolio',
        'posts_per_page' => 10,
    ];
    $tax_query = [];
    if (!empty($_GET['project_type'])) {
        $tax_query[] = [
            'taxonomy' => 'project_type',
            'field' => 'slug',
            'terms' => sanitize_text_field($_GET['project_type'])
        ];
    }
    if (!empty($_GET['technology'])) {
        $tax_query[] = [
            'taxonomy' => 'technology',
            'field' => 'slug',
            'terms' => sanitize_text_field($_GET['technology'])
        ];
    }
    if (!empty($tax_query)) {
        $args['tax_query'] = ['relation' => 'AND'] + $tax_query;
    }
    $query = new WP_Query($args);
    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            echo '<article class="portfolio-item">';
            echo '<h2><a href="' . get_permalink() . '">' . get_the_title() . '</a></h2>';
            echo '<div>' . get_the_excerpt() . '</div>';
            echo '</article>';
        }
        wp_reset_postdata();
    } else {
        echo '<p>Проекты не найдены.</p>';
    }
    wp_die();
}
add_action('wp_ajax_wp_theme_filter_portfolio', 'wp_theme_filter_portfolio_callback');
add_action('wp_ajax_nopriv_wp_theme_filter_portfolio', 'wp_theme_filter_portfolio_callback');

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

Использование плагина Clearfy Pro для оптимизации фильтров

Если вы используете тему с поддержкой плагина Clearfy Pro, то он поможет оптимизировать запросы, убрать лишние запросы к базе и ускорить работу фильтров. Это особенно полезно при большом количестве метаполей и таксономий.

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

Как создать динамические фильтры в теме WordPress для кастомных типов записей
13.12.2025
Как создать динамический журнал в WordPress с помощью REST API
23.11.2025
Оптимизация кода темы WordPress для улучшения производительности
15.01.2026
Как создать свою WordPress тему с нуля
04.11.2025
Как добавить поддержку Gutenberg в своей WordPress теме
27.11.2025