Как создать производительный каскадный выбор в WordPress с помощью AJAX

В этой статье разберем, как реализовать каскадный выбор (зависимые выпадающие списки) на сайте 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 и оптимизировать запросы с помощью кеширования. Надеюсь, пример и рекомендации помогут вам внедрить эффективный каскадный выбор на вашем сайте.

Как создать автоматическое отправление email в WordPress с помощью WP-Cron
01.04.2026
Как удалить базовые виджеты WordPress без ошибок и конфликтов
05.05.2026
Как добавить несколько обложек для записи в WordPress
13.01.2026
Как использовать хук WooCommerce before_add_to_cart для дополнительной логики
25.05.2026
Как автоматизировать удаление старых меню в WordPress
26.03.2026