Фильтры Ajax с несколькими аргументами tax_query

Вопрос или проблема

Я пытаюсь создать несколько ajax-фильтров, которые работают для нескольких таксономий. В конечном итоге у меня будет около 5 таксономий, но сейчас я пытаюсь заставить их работать только с двумя. Очевидно, у меня есть некоторые проблемы в этом коде.

Мне нужна помощь в двух вещах…

1 – Как добавить несколько аргументов tax_query?

Когда я добавляю второй, он ломается.

2 – Мне нужно, чтобы он запрашивал 1 таксономию И вторую, но обе могут быть необязательными. Также счетчик, созданный в меню, должен обновляться при выборе.

Если я добавляю только одну “tax_query”, она работает, но когда добавляю другую, ломается…

    query_posts(array(
        'post_type' => 'product',
        'post_status' => 'publish',
        'tax_query' => array(
            'relation' => 'AND',
            array(
                'taxonomy' => 'product_cat',
                'terms' => $_POST['product_cat'],
            ),
            array(
                'taxonomy' => 'sub_category',
                'terms' => $_POST['sub_category'],
            )
        )
    ));

Код для меню выбора

    <form id="product-filter" class="woocommerce-ordering">
        <?php
            $product_cats = get_terms( array(
                'taxonomy' => 'product_cat',
                'orderby' => 'name',
            ) );
            if( $product_cats ) :
                ?>
                    <select name="product_cat">
                        <option value="">Выберите категорию продуктов...</option>
                        <?php
                            foreach ( $product_cats as $product_cat ) :
                                ?><option value="<?php echo $product_cat->term_id ?>"><?php echo $product_cat->name ?> (<?php echo $product_cat->count ?>)</option><?php
                            endforeach;
                        ?>
                    </select>
                <?php
            endif;

            $sub_categories = get_terms( array(
                'taxonomy' => 'sub_category',
                'orderby' => 'name',
            ) );
            if($sub_categories) :
                ?>
                    <select name="sub_category">
                        <option value="">Выберите подкатегорию продуктов...</option>
                        <?php
                            foreach ($sub_categories as $sub_category) :
                                ?><option value="<?php echo $sub_category->term_id ?>"><?php echo $sub_category->name ?> (<?php echo $sub_category->count ?>)</option><?php
                            endforeach;
                        ?>
                    </select>
                <?php
            endif;
        ?>
    </form>

Часть PHP

    function gemcore_ui_filter_by_category() {
        query_posts(array(
            'post_type' => 'product',
            'post_status' => 'publish',
            'tax_query' => array(
                'relation' => 'AND',
                array(
                    'taxonomy' => 'product_cat',
                    'terms' => $_POST['product_cat'],
                ),
                array(
                    'taxonomy' => 'sub_category',
                    'terms' => $_POST['sub_category'],
                )
            )
        ));

        if(have_posts()) {
            while (have_posts()) {
                the_post();
                wc_get_template_part('content', 'product');
            }
        } else {
            echo 'Продукты в этой категории не найдены.';
        }

        die;
    }

    add_action('wp_ajax_productfilter', 'gemcore_ui_filter_by_category');
    add_action('wp_ajax_noprov_productfilter', 'gemcore_ui_filter_by_category');

AJAX часть (Я почти уверен, что мне не нужны оба вызова AJAX, но я еще не разобрался)

    hdsj.product_filters = hdsj.product_filters || {};

    hdsj.product_filters = {

        categories: function() {
            const productList = $('ul.products');

            $.ajax({
                url: product_filter_args.ajaxurl,
                method: 'POST',
                data: $('#product-filter').serialize(),
                beforeSend: function(xhr) {
                    // эффект предзагрузки, такой же, как используют WooCommerce корзина и оформление заказа
                    productList.fadeTo('400', '0.7').block({ message: null, overlayCSS: {opacity: 0.7,  backgroundColor: '#fff'}});
                },
                success: function(data) {
                    productList.stop(true).css('opacity', '1').unblock(); // удаляем предзагрузку
                    productList.html(data); // добавляем продукты в список
                    $('.woocommerce-pagination').remove(); // удаляем WooCommerce пагинацию
                }
            });
        },

        sub_categories: function() {
            const productList = $('ul.products');

            $.ajax({
                url: product_filter_args.ajaxurl,
                method: 'POST',
                data: $('#product-filter').serialize(),
                beforeSend: function(xhr) {
                    // эффект предзагрузки, такой же, как используют WooCommerce корзина и оформление заказа
                    productList.fadeTo('400', '0.7').block({ message: null, overlayCSS: {opacity: 0.7,  backgroundColor: '#fff'}});
                },
                success: function(data) {
                    productList.stop(true).css('opacity', '1').unblock(); // удаляем предзагрузку
                    productList.html(data); // добавляем продукты в список
                    $('.woocommerce-pagination').remove(); // удаляем WooCommerce пагинацию
                }
            });
        },

        init: function() {
            hdsj.product_filters.categories();
            hdsj.product_filters.sub_categories();
        }

    }

    $(document).ready(function() {

        $('select[name="product_cat"]').change(function() {
            hdsj.product_filters.init();
        });

        $('select[name="sub_category"]').change(function() {
            hdsj.product_filters.init();
        });

    });

Локализация скриптов

    wp_enqueue_script('custom_scripts', get_stylesheet_directory_uri() . '/js/custom-functions.js', array('jquery', 'jquery-blockui'), filemtime(get_stylesheet_directory() . '/js/custom-functions.js'));

    wp_localize_script(
        'custom_scripts',
        'product_filter_args',
        array(
            'ajaxurl' => add_query_arg(array('action' => 'productfilter'), admin_url('admin-ajax.php')),
        )
    );
    wp_enqueue_script('custom_scripts');

Ответ или решение

Создание Ajax фильтров с несколькими аргументами tax_query для WordPress может быть сложной задачей, особенно когда существует потребность гибко обрабатывать несколько таксономий. Давайте рассмотрим, как можно эффективно решить вашу проблему.

Теория

Работа с несколькими таксономиями в WP_Query предполагает использование параметра tax_query, который позволяет фильтровать результаты на основе таксономических терминов. При добавлении нескольких таксономий нужно правильно использовать массивы и параметр ‘relation’, который позволяет настраивать логику объединения (И/ИЛИ).

Пример

В вашем случае вы хотите использовать две таксономии: product_cat и sub_category. Задача заключается в том, чтобы оба термина могли быть выбраны пользователем произвольно, и чтобы AJAX-запрос возвращал соответствующие результаты:

PHP Код

function gemcore_ui_filter_by_category() {
    $args = array(
        'post_type' => 'product',
        'post_status' => 'publish',
        'tax_query' => array(
            'relation' => 'AND',
        ),
    );

    if (!empty($_POST['product_cat'])) {
        $args['tax_query'][] = array(
            'taxonomy' => 'product_cat',
            'terms' => $_POST['product_cat'],
        );
    }

    if (!empty($_POST['sub_category'])) {
        $args['tax_query'][] = array(
            'taxonomy' => 'sub_category',
            'terms' => $_POST['sub_category'],
        );
    }

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            wc_get_template_part('content', 'product');
        }
    } else {
        echo 'No products found in this category.';
    }

    wp_reset_postdata();
    die;
}

add_action('wp_ajax_productfilter', 'gemcore_ui_filter_by_category');
add_action('wp_ajax_nopriv_productfilter', 'gemcore_ui_filter_by_category');

Применение

  1. Корректная передача данных. Убедитесь, что ваши AJAX-запросы корректно сериализуют данные формы. Функция $('#product-filter').serialize() полезна и эффективна, но также важно проверить, существуют ли данные в $_POST.

  2. Гибкость запроса. Вышеуказанный код показывает, как можно добавлять элементы массива tax_query только если они действительно существуют в POST-запросе. Это помогает предотвратить создание пустых условий, которые могли бы вызвать сбой в запросе.

  3. Обновление счетчиков в селекторах. Чтобы счетчик товарных категорий обновлялся, необходимо обновить метаданные о количестве товаров на стороне клиента при получении нового набора данных. Это можно сделать, модифицировав ваш JavaScript код, чтобы он вызывал обновления DOM после каждой успешной загрузки данных.

  4. Оптимизация AJAX вызовов. Удалите избыточные функции AJAX. В данном случае, одна функция обработки данных отрабатывает корректно. В коде JavaScript следует вызывать только необходимый метод, а сам метод должен быть адаптирован под нужды обеих таксономий:

hdsj.product_filters = {
    filterProducts: function() {
        const productList = $('ul.products');

        $.ajax({
            url: product_filter_args.ajaxurl,
            method: 'POST',
            data: $('#product-filter').serialize(),
            beforeSend: function(xhr) {
                productList.fadeTo('400', '0.7').block({ message: null, overlayCSS: { opacity: 0.7, backgroundColor: '#fff' } });
            },
            success: function(data) {
                productList.stop(true).css('opacity', '1').unblock();
                productList.html(data);
                $('.woocommerce-pagination').remove();
            }
        });
    },
    init: function() {
        $('select[name="product_cat"]').change(function() {
            hdsj.product_filters.filterProducts();
        });

        $('select[name="sub_category"]').change(function() {
            hdsj.product_filters.filterProducts();
        });
    }
};

$(document).ready(function() {
    hdsj.product_filters.init();
});

Заключение

Решение проблемы с использованием AJAX-фильтров с несколькими таксономиями в WordPress требует аккуратного подхода к настройкам tax_query, гибкости в определении логики, а также оптимизации клиентского кода. Убедитесь, что все части сети (от отправки формы до обработки ответа и обновления интерфейса) функционируют согласовано и эффективно. Это обеспечит не только правильную работу вашего фильтра, но и улучшит пользовательский опыт.

Оцените материал
Добавить комментарий

Капча загружается...