HUSKY - Product Filter for WooCommerce

Фильтр WooCommerce по категории не возвращает результатов: исправление иерархии категорий

Если фильтр WooCommerce по категориям не возвращает результатов для родительских категорий, даже если товары назначены дочерним категориям, это руководство поможет вам решить эту проблему.

Проблема

Симптом: При фильтрации по родительской категории товары не отображаются, хотя они существуют в ее дочерних категориях.

Пример:

  • Структура категории: Federal Actions > SEC > Enforcement
  • Товар назначен: Enforcement (только дочерняя категория)
  • Фильтрация по Federal Actions or SEC возвращает: Нет результатов
  • Filtering by Enforcement returns: Товар показан

Почему это происходит

WordPress/WooCommerce требует явно отмечать товары всеми родительскими категориями в иерархии, а не только дочерней категорией.

Когда вы назначаете товар дочерней категории через интерфейс администратора WordPress, WooCommerce автоматически не помечает товар всеми родительскими категориями в таблице отношений терминов. Это требование структуры данных, а не ограничение HUSKY.

Правильное назначение категории должно включать:

  • Дочерняя категория: Enforcement
  • Родительская категория: SEC
  • Категория-бабушка: Federal Actions

Как проверить, есть ли у вас эта проблема

  1. Перейдите на страницу редактирования товара: wp-admin/post.php?post=YOUR_PRODUCT_ID&action=edit
  2. Посмотрите на метабокс "Категории" справа
  3. Проверьте, отмечены ли all parent categories в иерархии
  4. Если отмечена только дочерняя категория → У вас эта проблема

Решение: Автоматическая нормализация иерархии категорий

Это решение состоит из двух частей:

  1. Решение на будущее: Автоматически отмечать родительские категории при сохранении товаров
  2. Немедленное решение: Нормализовать все существующие товары

Часть 1: Автоматическая маркировка родительских категорий (будущие товары)

Добавьте этот код в свой дочерний файл темы functions.php:

/**
 * Automatically mark all parent categories when product is saved
 * This ensures hierarchy filtering works correctly
 */
add_action('save_post_product', 'auto_mark_parent_categories', 10, 1);

function auto_mark_parent_categories($product_id) {
    // Clear cache
    clean_object_term_cache($product_id, 'product_cat');

    // Get currently assigned categories
    $terms = wp_get_post_terms($product_id, 'product_cat', ['fields' => 'ids']);

    if (!is_wp_error($terms) AND !empty($terms)) {
        $all_terms = [];

        // For each assigned category, get all its parents
        foreach ($terms as $term_id) {
            $all_terms[] = $term_id;

            // Get all ancestor categories
            $ancestors = get_ancestors($term_id, 'product_cat', 'taxonomy');
            if (!empty($ancestors)) {
                $all_terms = array_merge($all_terms, $ancestors);
            }
        }

        // Assign product to all categories including parents
        wp_set_object_terms($product_id, array_unique($all_terms), 'product_cat');

        // Clear caches
        clean_post_cache($product_id);
        clean_object_term_cache($product_id, 'product_cat');

        if (function_exists('wc_delete_product_transients')) {
            wc_delete_product_transients($product_id);
        }
    }
}

Что это делает:

  • Срабатывает каждый раз при сохранении товара
  • Получает все назначенные категории
  • Находит все родительские категории для каждой назначенной категории
  • Отмечает товар полной иерархией
  • Очищает все соответствующие кэши

Результат: С этого момента любой сохраненный товар будет автоматически включать все родительские категории.

Часть 2: Нормализация существующих товаров (разовое исправление)

Этот скрипт исправит все существующие товары в вашей базе данных. Добавьте этот временный код в свой functions.php:

/**
 * One-time script to normalize all existing products
 * Access: yourdomain.com/?normalize_cats=1 (must be logged in as admin)
 */
add_action('init', function () {
    if (isset($_GET['normalize_cats']) AND current_user_can('manage_options')) {
        $result = normalize_all_products_categories();
        echo '<h2>Category Normalization Results</h2>';
        echo '<pre>';
        print_r($result);
        echo '</pre>';
        die();
    }
});

function normalize_all_products_categories() {
    global $wpdb;

    // Get all product IDs
    $args = [
        'post_type' => 'product',
        'post_status' => 'any',
        'posts_per_page' => -1,
        'fields' => 'ids'
    ];

    $product_ids = get_posts($args);
    $log = [];
    $normalized_count = 0;

    foreach ($product_ids as $product_id) {
        // Get current categories
        $terms = wp_get_post_terms($product_id, 'product_cat', ['fields' => 'ids']);

        if (!is_wp_error($terms) AND !empty($terms)) {
            $all_terms = [];

            // Collect all parent categories
            foreach ($terms as $term_id) {
                $all_terms[] = $term_id;

                // Get ancestors
                $ancestors = get_ancestors($term_id, 'product_cat', 'taxonomy');

                if (!empty($ancestors)) {
                    $all_terms = array_merge($all_terms, $ancestors);
                }
            }

            $all_terms = array_unique($all_terms);

            // Only update if we're adding new parent categories
            if (count($all_terms) > count($terms)) {
                wp_set_object_terms($product_id, $all_terms, 'product_cat');
                $normalized_count++;
                $log[] = "Product #{$product_id}: added " . (count($all_terms) - count($terms)) . " parent categories";
            }
        }
    }

    // Log to WordPress error log
    error_log("=== Category Normalization Complete ===");
    error_log(implode("\n", $log));
    error_log("Total normalized: {$normalized_count} products");

    return [
        'success' => true,
        'normalized' => $normalized_count,
        'total' => count($product_ids),
        'details' => $log
    ];
}

Как использовать:

  1. Добавьте код в свой functions.php
  2. Перейдите по адресу: https://yoursite.com/?normalize_cats=1 (должен быть выполнен вход в качестве администратора)
  3. Подождите, пока скрипт завершится
  4. Вы увидите результаты, показывающие, сколько товаров было обновлено
  5. Удалите этот код после однократного запуска

Ожидаемый вывод:

Category Normalization Results
Array
(
    [success] => 1
    [normalized] => 156
    [total] => 919
)

Это означает, что 156 из 919 товаров не имели родительских категорий и были исправлены.

Тестирование исправления

После реализации обеих частей:

  1. Перейдите на страницу вашего магазина с фильтрами HUSKY
  2. Попробуйте фильтровать по родительской категории
  3. Товары из дочерних категорий теперь должны отображаться
  4. Попробуйте пройтись по иерархии — все уровни должны работать

Почему бы не сделать это настройкой по умолчанию в HUSKY?

Это обоснованный вопрос. Вот почему:

  1. Изменение структуры данных: Это изменяет основные связи данных WooCommerce
  2. Не универсально: Некоторые сайты намеренно присваивают только дочерние категории для конкретной бизнес-логики
  3. Производительность: На очень больших каталогах это увеличивает нагрузку на каждое сохранение товара
  4. Конфликты: Может конфликтовать с другими плагинами, управляющими связями категорий

Будущее улучшение: Мы можем добавить это как опциональную настройку в HUSKY, которую пользователи смогут включить при необходимости, но это не будет поведением по умолчанию.

Альтернатива: ручное назначение категорий

Если вы предпочитаете ручное управление, вы можете:

  1. Отредактировать каждый товар
  2. В метабоксе "Категории" отметьте все соответствующие родительские категории вручную
  3. Сохраните товар

Это дает вам детальный контроль, но занимает много времени для больших каталогов.

Устранение неполадок

Скрипт показывает 0 нормализованных товаров

  • Ваши товары, возможно, уже имеют правильно назначенные родительские категории
  • Проверьте несколько товаров вручную, чтобы убедиться

Фильтрация все еще не работает после нормализации

  • Очистите все кэши (WordPress, сервер, браузер)
  • Убедитесь, что HUSKY использует правильную таксономию (product_cat)
  • Проверьте конфликты с другими плагинами фильтрации
  • Убедитесь, что товары опубликованы (не черновики)

Товары исчезают из фильтра дочерних категорий

Такого не должно происходить, но если это случилось:

  • Скрипт сохраняет все существующие назначения категорий
  • Проверьте, не вмешивается ли другой плагин
  • Восстановите из резервной копии и свяжитесь с поддержкой

Пользовательские таксономии

Это решение также работает для пользовательских таксономий , созданных с помощью CPT UI или аналогичных плагинов. Просто измените 'product_cat' на слаг вашей пользовательской таксономии:

// Example for custom taxonomy 'modality'
$terms = wp_get_post_terms($product_id, 'modality', ['fields' => 'ids']);
wp_set_object_terms($product_id, array_unique($all_terms), 'modality');

Важные замечания

  • Требуется дочерняя тема: Всегда используйте дочернюю тему, чтобы избежать потери кода при обновлении темы
  • Сначала сделайте резервную копию: Сделайте резервную копию вашей базы данных перед запуском скрипта нормализации
  • Тестируйте на staging-сайте: По возможности сначала протестируйте на staging-сайте
  • Одноразовый скрипт: Удалите скрипт нормализации после его запуска
  • Сохраните код Части 1: save_post_product хук должен остаться навсегда

Итог

Добавьте в functions.php навсегда:

  • Хук автоматической маркировки родительских категорий (Часть 1)

Запустить один раз и удалить:

  • Скрипт нормализации (Часть 2)

Ожидаемые результаты:

  • Фильтрация родительских категорий работает корректно
  • Фильтрация дочерних категорий продолжает работать
  • Режим древовидного раскрытия работает правильно
  • Будущие товары автоматически включают родительские категории