WooCommerce: как добавить кастомный фильтр по атрибутам в GeneratePress

Диагностика задачи: зачем нужен кастомный фильтр по атрибутам

В стандартном функционале WooCommerce фильтрация товаров по атрибутам реализована через виджет «Фильтр по атрибутам». Однако он ограничен по дизайну и функциональности, особенно в темах типа GeneratePress, где требуется более гибкая интеграция в макет и стили. Если вы хотите вывести фильтр по атрибутам в виде кастомного блока с возможностью AJAX-подгрузки и без перезагрузки страницы, придется реализовывать фильтр вручную.

Как добавить кастомный фильтр по атрибутам в GeneratePress

1. Создаем shortcode для фильтра атрибутов

Добавьте следующий код в файл functions.php вашей дочерней темы GeneratePress или в плагин для кастомного кода:

function gp_custom_attribute_filter_shortcode( $atts ) {
    if ( ! class_exists( 'WooCommerce' ) ) {
        return 'WooCommerce не активирован';
    }
    $atts = shortcode_atts( array(
        'attribute' => '', // slug атрибута, например color
    ), $atts, 'gp_attr_filter' );

    if ( empty( $atts['attribute'] ) ) {
        return 'Атрибут не задан';
    }

    $taxonomy = 'pa_' . sanitize_title( $atts['attribute'] );
    if ( ! taxonomy_exists( $taxonomy ) ) {
        return 'Атрибут не существует';
    }

    $terms = get_terms( array(
        'taxonomy' => $taxonomy,
        'hide_empty' => true,
    ) );

    if ( is_wp_error( $terms ) || empty( $terms ) ) {
        return 'Нет доступных значений для атрибута';
    }

    ob_start();
    ?>
    <form id="gp-attr-filter-form">
        <?php foreach ( $terms as $term ): ?>
            <label>
                <input type="checkbox" name="filter_<?php echo esc_attr($taxonomy); ?>" value="<?php echo esc_attr($term->slug); ?>" />
                <?php echo esc_html($term->name); ?>
            </label><br />
        <?php endforeach; ?>
        <button type="submit">Фильтровать</button>
    </form>
    <div id="gp-filter-results"></div>
    <?php
    return ob_get_clean();
}
add_shortcode( 'gp_attr_filter', 'gp_custom_attribute_filter_shortcode' );

2. Добавляем AJAX обработчик для фильтрации товаров

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

function gp_filter_products_by_attribute() {
    if ( empty( $_POST['attribute'] ) || empty( $_POST['values'] ) ) {
        wp_send_json_error( 'Не переданы параметры фильтра' );
    }

    $attribute = sanitize_text_field( $_POST['attribute'] );
    $values = array_map( 'sanitize_text_field', (array) $_POST['values'] );
    $taxonomy = 'pa_' . $attribute;

    $args = array(
        'post_type' => 'product',
        'posts_per_page' => 12,
        'tax_query' => array(
            array(
                'taxonomy' => $taxonomy,
                'field' => 'slug',
                'terms' => $values,
                'operator' => 'IN',
            ),
        ),
    );

    $query = new WP_Query( $args );

    ob_start();
    if ( $query->have_posts() ) {
        woocommerce_product_loop_start();
        while ( $query->have_posts() ) {
            $query->the_post();
            wc_get_template_part( 'content', 'product' );
        }
        woocommerce_product_loop_end();
    } else {
        echo '<p>Товары не найдены.</p>';
    }
    wp_reset_postdata();

    $html = ob_get_clean();
    wp_send_json_success( $html );
}
add_action( 'wp_ajax_gp_filter_products', 'gp_filter_products_by_attribute' );
add_action( 'wp_ajax_nopriv_gp_filter_products', 'gp_filter_products_by_attribute' );

3. Скрипт для отправки AJAX-запроса

Добавьте в footer или подключите отдельный JS-файл с таким кодом (пример для простоты через inline-скрипт):

function gp_enqueue_filter_scripts() {
    wp_enqueue_script( 'gp-filter-js', get_stylesheet_directory_uri() . '/js/gp-filter.js', array( 'jquery' ), '1.0', true );
    wp_localize_script( 'gp-filter-js', 'gpFilter', array(
        'ajaxurl' => admin_url( 'admin-ajax.php' ),
    ) );
}
add_action( 'wp_enqueue_scripts', 'gp_enqueue_filter_scripts' );

В файле js/gp-filter.js:

jQuery(document).ready(function($) {
    $('#gp-attr-filter-form').on('submit', function(e) {
        e.preventDefault();
        var attribute = '<?php echo esc_js( $atts['attribute'] ); ?>'; // заменить при интеграции
        var values = [];
        $('input[name^="filter_pa_"]:checked').each(function() {
            values.push($(this).val());
        });
        if (values.length === 0) {
            $('#gp-filter-results').html('<p>Пожалуйста, выберите хотя бы один вариант.</p>');
            return;
        }
        $('#gp-filter-results').html('<p>Загрузка...</p>');
        $.post(gpFilter.ajaxurl, {
            action: 'gp_filter_products',
            attribute: attribute,
            values: values
        }, function(response) {
            if (response.success) {
                $('#gp-filter-results').html(response.data);
            } else {
                $('#gp-filter-results').html('<p>Ошибка при загрузке товаров.</p>');
            }
        });
    });
});

Проверка результата после внедрения

1. Вставьте шорткод в нужное место, например в страницу или виджет: [gp_attr_filter attribute="color"] (замените «color» на нужный slug атрибута).
2. Откройте страницу с фильтром, отметьте несколько чекбоксов и нажмите «Фильтровать».
3. В блоке результатов должны появиться товары, соответствующие выбранным атрибутам, без перезагрузки страницы.
4. Проверьте консоль браузера на отсутствие JavaScript ошибок.
5. Если товаров нет, выведется соответствующее сообщение.

Частые ошибки и как их исправить

  • Ошибка: «Атрибут не существует». Проверьте правильность slug атрибута. В WooCommerce slug атрибута начинается с «pa_» в базе, убедитесь, что передаете только его имя без префикса.
  • AJAX не работает, при нажатии кнопки ничего не происходит. Проверьте подключение jQuery, правильность локализации скрипта и наличие элемента с id gp-attr-filter-form.
  • Появляются товары без фильтрации. Убедитесь, что в запросе WP_Query правильно настроен параметр tax_query и передаются корректные значения.
  • Фильтр не отображается. Убедитесь, что шорткод вставлен корректно и WooCommerce активен.

Практические советы по производительности и безопасности

  • При большом количестве товаров и атрибутов используйте кэширование результатов AJAX, например через Transients API, чтобы снизить нагрузку на базу данных.
  • Обязательно проверяйте и фильтруйте все входящие данные в AJAX для предотвращения XSS и других уязвимостей.
  • Для корректной работы AJAX на фронтенде используйте wp_localize_script, чтобы передавать URL и nonce, если реализуете защиту.
  • Рассмотрите использование плагинов типа Clearfy Pro (https://wpshop.ru/plugins/clearfy?utm_source=generatepress.ru&utm_medium=article&utm_campaign=woocommerce-kak-dobavit-kastomnyj-filtr-po-atributam-v-generatepress) для оптимизации сайта и удаления лишних запросов.

Сравнение способов реализации фильтра

МетодПреимуществаНедостатки
Стандартный виджет WooCommerceПростота настройки, интеграция с WooCommerceОграниченный дизайн, перезагрузка страницы
Кастомный шорткод + AJAX (описанный)Гибкость дизайна, быстрая фильтрация без перезагрузкиТребует навыков программирования, поддержка кода
Плагины фильтрации (FacetWP, Filter Everything)Много функций, готовые решенияПлатные, дополнительная нагрузка
Как добавить отложенную загрузку картинок в GeneratePress для ускорения сайта
23.01.2026
Как добавить уникальные метаданные для страниц в GeneratePress
09.12.2025
Как создать внутреннюю кэширу в GeneratePress для ускорения загрузки сайта
30.03.2026
Как добавить кастомные виджеты в GeneratePress с помощью кода
12.12.2025
Как организовать каскадные стили в GeneratePress без конфликтов
30.01.2026