Диагностика задачи: зачем нужен кастомный фильтр по атрибутам
В стандартном функционале 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) | Много функций, готовые решения | Платные, дополнительная нагрузка |