Вопрос или проблема
Я пытаюсь создать несколько 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');
Применение
-
Корректная передача данных. Убедитесь, что ваши AJAX-запросы корректно сериализуют данные формы. Функция
$('#product-filter').serialize()
полезна и эффективна, но также важно проверить, существуют ли данные в$_POST
. -
Гибкость запроса. Вышеуказанный код показывает, как можно добавлять элементы массива
tax_query
только если они действительно существуют в POST-запросе. Это помогает предотвратить создание пустых условий, которые могли бы вызвать сбой в запросе. -
Обновление счетчиков в селекторах. Чтобы счетчик товарных категорий обновлялся, необходимо обновить метаданные о количестве товаров на стороне клиента при получении нового набора данных. Это можно сделать, модифицировав ваш JavaScript код, чтобы он вызывал обновления DOM после каждой успешной загрузки данных.
-
Оптимизация 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
, гибкости в определении логики, а также оптимизации клиентского кода. Убедитесь, что все части сети (от отправки формы до обработки ответа и обновления интерфейса) функционируют согласовано и эффективно. Это обеспечит не только правильную работу вашего фильтра, но и улучшит пользовательский опыт.