В этой статье разберем, как реализовать каскадный выбор (зависимые выпадающие списки) на сайте WordPress с использованием AJAX. Такая функциональность полезна, если, например, нужно выбрать сначала категорию товаров, затем подкатегорию и наконец конкретный товар, при этом без перезагрузки страницы. Мы рассмотрим, как сделать это эффективно и с минимальной нагрузкой на сервер.
Что такое каскадный выбор и зачем использовать AJAX
Каскадный выбор — это несколько связанных между собой выпадающих списков (select), где выбор в одном влияет на содержимое следующего. Например, при выборе региона подгружаются города этого региона, а затем районы.
Если загружать все данные сразу, это может быть тяжело при большом объеме. А если подгружать при выборе — пользователь получает быстрый отклик и не ждет полной загрузки всех данных. Для этого идеально подходит AJAX — асинхронный запрос к серверу без перезагрузки страницы.
В WordPress AJAX-запросы обрабатываются через специальные хуки и функции. Рассмотрим пример создания такого каскадного выбора для произвольных таксономий.
Подготовка таксономий и кастомных типов записей
Предположим, у нас есть кастомный тип записей product и две таксономии: product_cat и product_subcat, где подкатегории зависят от категорий.
Регистрируем их в файле вашего плагина или темы:
function wplesson_register_custom_taxonomies() {
register_taxonomy('product_cat', 'product', [
'hierarchical' => true,
'label' => 'Категории товаров',
'show_ui' => true,
]);
register_taxonomy('product_subcat', 'product', [
'hierarchical' => true,
'label' => 'Подкатегории товаров',
'show_ui' => true,
]);
}
add_action('init', 'wplesson_register_custom_taxonomies');Важно, чтобы подкатегории имели связь с категориями через метаданные или иерархию, в зависимости от вашей логики. В простом случае можно использовать родительские термины для подкатегорий.
Создание HTML формы с выпадающими списками
В шаблоне или в шорткоде создадим форму с двумя выпадающими списками: категории и подкатегории. По умолчанию подкатегории пусты и подгружаются по выбору категории.
function wplesson_render_cascade_select() {
$categories = get_terms(['taxonomy' => 'product_cat', 'hide_empty' => false]);
ob_start();
?>
<select id="wplesson_product_cat">
<option value="">Выберите категорию</option>
<?php foreach($categories as $cat): ?>
<option value="<?php echo esc_attr($cat->term_id); ?>"><?php echo esc_html($cat->name); ?></option>
<?php endforeach; ?>
</select>
<select id="wplesson_product_subcat" disabled>
<option value="">Выберите подкатегорию</option>
</select>
<script>
jQuery(document).ready(function($){
$('#wplesson_product_cat').on('change', function(){
var catID = $(this).val();
if(!catID) {
$('#wplesson_product_subcat').html('<option value="">Выберите подкатегорию</option>').prop('disabled', true);
return;
}
$('#wplesson_product_subcat').prop('disabled', true).html('<option>Загрузка...</option>');
$.ajax({
url: wplesson_ajax_object.ajax_url,
method: 'POST',
data: {
action: 'wplesson_get_subcategories',
category_id: catID,
nonce: wplesson_ajax_object.nonce
},
success: function(response){
if(response.success) {
var options = '<option value="">Выберите подкатегорию</option>';
$.each(response.data, function(i, item){
options += '<option value="'+item.term_id+'">'+item.name+'</option>';
});
$('#wplesson_product_subcat').html(options).prop('disabled', false);
} else {
$('#wplesson_product_subcat').html('<option>Ошибка загрузки</option>').prop('disabled', true);
}
},
error: function(){
$('#wplesson_product_subcat').html('<option>Ошибка запроса</option>').prop('disabled', true);
}
});
});
});
</script>
<?php
return ob_get_clean();
}
add_shortcode('wplesson_cascade_select', 'wplesson_render_cascade_select');Обратите внимание, что в JS используется объект wplesson_ajax_object с параметрами AJAX, который нужно добавить в локализацию скрипта, чтобы передать URL и nonce.
Обработка AJAX запроса в WordPress
Теперь создадим обработчик AJAX, который на сервере вернет подкатегории выбранной категории.
function wplesson_get_subcategories_ajax() {
check_ajax_referer('wplesson_nonce', 'nonce');
$category_id = intval($_POST['category_id'] ?? 0);
if(!$category_id) {
wp_send_json_error('Неверный ID категории');
}
$args = [
'taxonomy' => 'product_subcat',
'hide_empty' => false,
'meta_query' => [
[
'key' => 'parent_cat_id', // предположим, что связь через метаполе
'value' => $category_id,
'compare' => '=',
]
]
];
$subcategories = get_terms($args);
if(is_wp_error($subcategories)) {
wp_send_json_error('Ошибка получения подкатегорий');
}
$result = [];
foreach($subcategories as $subcat) {
$result[] = ['term_id' => $subcat->term_id, 'name' => $subcat->name];
}
wp_send_json_success($result);
}
add_action('wp_ajax_wplesson_get_subcategories', 'wplesson_get_subcategories_ajax');
add_action('wp_ajax_nopriv_wplesson_get_subcategories', 'wplesson_get_subcategories_ajax');Важный момент — должна быть реализована логика связывания подкатегорий с категориями, в примере это метаполе parent_cat_id у терминов подкатегорий. Если вы используете иерархию таксономии, можно сделать запрос по родителю.
Регистрация и локализация скриптов
Чтобы JS получил правильный URL AJAX и nonce для безопасности, подключаем скрипт и локализуем данные:
function wplesson_enqueue_scripts() {
wp_enqueue_script('wplesson-cascade-select', get_template_directory_uri() . '/js/wplesson-cascade-select.js', ['jquery'], null, true);
wp_localize_script('wplesson-cascade-select', 'wplesson_ajax_object', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wplesson_nonce'),
]);
}
add_action('wp_enqueue_scripts', 'wplesson_enqueue_scripts');В нашем примере JS код встроен прямо в шорткод, но в реальном проекте лучше вынести его в отдельный файл и подключить так, как показано выше.
Оптимизация и кеширование
Для повышения производительности рекомендуется кешировать результаты AJAX запросов. Можно использовать Transients API:
function wplesson_get_subcategories_ajax() {
check_ajax_referer('wplesson_nonce', 'nonce');
$category_id = intval($_POST['category_id'] ?? 0);
if(!$category_id) {
wp_send_json_error('Неверный ID категории');
}
$cache_key = 'wplesson_subcats_'. $category_id;
$cached = get_transient($cache_key);
if($cached !== false) {
wp_send_json_success($cached);
}
$args = [
'taxonomy' => 'product_subcat',
'hide_empty' => false,
'meta_query' => [
[
'key' => 'parent_cat_id',
'value' => $category_id,
'compare' => '=',
]
]
];
$subcategories = get_terms($args);
if(is_wp_error($subcategories)) {
wp_send_json_error('Ошибка получения подкатегорий');
}
$result = [];
foreach($subcategories as $subcat) {
$result[] = ['term_id' => $subcat->term_id, 'name' => $subcat->name];
}
set_transient($cache_key, $result, HOUR_IN_SECONDS);
wp_send_json_success($result);
}Это снизит нагрузку на базу данных при повторных запросах.
Пример использования плагина Clearfy Pro для оптимизации AJAX
Если на сайте установлен плагин Clearfy Pro, можно дополнительно оптимизировать AJAX-запросы за счет отключения ненужных скриптов и стили, а также ускорить работу REST API, что положительно скажется на производительности каскадного выбора.
Вывод
Создание каскадного выбора с использованием AJAX в WordPress — задача вполне выполнимая с помощью стандартных средств. Такой подход улучшает UX, снижает нагрузку на сервер и позволяет гибко работать с большими объемами данных. Важно обеспечить безопасность через nonce и оптимизировать запросы с помощью кеширования. Надеюсь, пример и рекомендации помогут вам внедрить эффективный каскадный выбор на вашем сайте.