HUSKY - Product Filter for WooCommerce

Filtr WooCommerce według kategorii nie zwraca wyników: Naprawa hierarchii kategorii

Jeśli filtr WooCommerce według kategorii nie zwraca wyników dla kategorii nadrzędnych, mimo że produkty są przypisane do kategorii podrzędnych, ten przewodnik pomoże Ci to naprawić.

Problem

Objaw: Gdy filtrujesz według kategorii nadrzędnej, nie są wyświetlane żadne produkty, mimo że produkty istnieją w jej kategoriach podrzędnych.

Przykład:

  • Struktura kategorii: Federal Actions > SEC > Enforcement
  • Produkt jest przypisany do: Enforcement (tylko kategoria podrzędna)
  • Filtrowanie według Federal Actions lub SEC zwraca: Brak wyników
  • Filtrowanie według Enforcement zwraca: Produkt wyświetlony

Dlaczego tak się dzieje

WordPress/WooCommerce wymaga , aby produkty były jawnie oznaczone wszystkimi kategoriami nadrzędnymi w hierarchii, a nie tylko kategorią podrzędną.

Gdy przypisujesz produkt do kategorii podrzędnej przez panel administracyjny WordPress, WooCommerce nie oznacza automatycznie produktu wszystkimi kategoriami nadrzędnymi w tabeli relacji terminów. Jest to wymóg struktury danych, a nie ograniczenie HUSKY.

Prawidłowe przypisanie kategorii powinno obejmować:

  • Kategoria podrzędna: Enforcement
  • Kategoria nadrzędna: SEC
  • Kategoria nadrzędna drugiego stopnia: Federal Actions

Jak sprawdzić, czy masz ten problem

  1. Przejdź do strony edycji produktu: wp-admin/post.php?post=YOUR_PRODUCT_ID&action=edit
  2. Spójrz na metabox Kategorie po prawej stronie
  3. Sprawdź, czy wszystkie kategorie nadrzędne w hierarchii są zaznaczone
  4. Jeśli zaznaczona jest tylko kategoria podrzędna → Masz ten problem

Rozwiązanie: Automatyczna normalizacja hierarchii kategorii

To rozwiązanie składa się z dwóch części:

  1. Poprawka na przyszłość: Automatyczne oznaczanie kategorii nadrzędnych podczas zapisywania produktów
  2. Natychmiastowa poprawka: Normalizacja wszystkich istniejących produktów

Część 1: Automatyczne oznaczanie kategorii nadrzędnych (przyszłe produkty)

Dodaj ten kod do pliku functions.php swojego motywu potomnego:

/**
 * 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);
        }
    }
}

Co to robi:

  • Wyzwala się za każdym razem, gdy produkt jest zapisywany
  • Pobiera wszystkie przypisane kategorie
  • Znajduje wszystkie kategorie nadrzędne dla każdej przypisanej kategorii
  • Oznacza produkt pełną hierarchią
  • Czyści wszystkie odpowiednie pamięci podręczne

Wynik: Od teraz każdy zapisany produkt będzie automatycznie zawierał wszystkie kategorie nadrzędne.

Część 2: Normalizacja istniejących produktów (jednorazowa poprawka)

Ten skrypt naprawi wszystkie istniejące produkty w Twojej bazie danych. Dodaj ten tymczasowy kod do swojego pliku 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
    ];
}

Jak użyć:

  1. Dodaj kod do swojego pliku functions.php
  2. Przejdź do: https://yoursite.com/?normalize_cats=1 (musisz być zalogowany jako administrator)
  3. Poczekaj na zakończenie skryptu
  4. Zobaczysz wyniki pokazujące, ile produktów zostało zaktualizowanych
  5. Usuń ten kod po jednokrotnym uruchomieniu

Oczekiwany wynik:

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

Oznacza to, że 156 produktów z 919 brakowało kategorii nadrzędnych i zostało naprawionych.

Testowanie poprawki

Po wdrożeniu obu części:

  1. Przejdź do strony sklepu z filtrami HUSKY
  2. Spróbuj filtrować według kategorii nadrzędnej
  3. Produkty z kategorii podrzędnych powinny się teraz pojawić
  4. Spróbuj zagłębić się w hierarchię – wszystkie poziomy powinny działać

Dlaczego nie uczynić tego domyślnym w HUSKY?

To uzasadnione pytanie. Oto dlaczego:

  1. Zmiana struktury danych: To modyfikuje podstawowe relacje danych WooCommerce
  2. Nieuniwersalne: Niektóre witryny celowo przypisują tylko kategorie podrzędne ze względu na określoną logikę biznesową
  3. Wydajność: Przy bardzo dużych katalogach dodaje to narzutu przy każdym zapisie produktu
  4. Konflikty: Może kolidować z innymi wtyczkami zarządzającymi relacjami kategorii

Przyszłe ulepszenie: Możemy dodać to jako opcjonalne ustawienie w HUSKY, które użytkownicy będą mogli włączyć, jeśli zajdzie taka potrzeba, ale nie będzie to domyślne zachowanie.

Alternatywa: Ręczne przypisywanie kategorii

Jeśli wolisz ręczną kontrolę, możesz:

  1. Edytuj każdy produkt
  2. W metaboxie Kategorie zaznacz ręcznie wszystkie odpowiednie kategorie nadrzędne
  3. Zapisz produkt

Daje to szczegółową kontrolę, ale jest czasochłonne w przypadku dużych katalogów.

Rozwiązywanie problemów

Skrypt pokazuje 0 znormalizowanych produktów

  • Twoje produkty mogą już mieć poprawnie przypisane kategorie nadrzędne
  • Sprawdź ręcznie kilka produktów, aby to zweryfikować

Filtrowanie nadal nie działa po normalizacji

  • Wyczyść wszystkie pamięci podręczne (WordPress, serwer, przeglądarka)
  • Upewnij się, że HUSKY używa prawidłowej taksonomii (product_cat)
  • Sprawdź konflikty z innymi wtyczkami filtrującymi
  • Sprawdź, czy produkty są opublikowane (nie wersje robocze)

Produkty znikają z filtra kategorii podrzędnej

To nie powinno się zdarzyć, ale jeśli tak się stanie:

  • Skrypt zachowuje wszystkie istniejące przypisania kategorii
  • Sprawdź, czy inna wtyczka nie przeszkadza
  • Przywróć z kopii zapasowej i skontaktuj się z pomocą techniczną

Taksonomie niestandardowe

To rozwiązanie działa również dla taksonomii niestandardowych utworzonych za pomocą CPT UI lub podobnych wtyczek. Po prostu zmień 'product_cat' na slug swojej taksonomii niestandardowej:

// 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');

Ważne uwagi

  • Wymagany motyw potomny: Zawsze używaj motywu potomnego, aby zapobiec utracie kodu podczas aktualizacji motywu
  • Najpierw kopia zapasowa: Wykonaj kopię zapasową bazy danych przed uruchomieniem skryptu normalizacji
  • Testuj na środowisku testowym: Jeśli to możliwe, najpierw przetestuj na stronie testowej
  • Skrypt jednorazowy: Usuń skrypt normalizacji po jego uruchomieniu
  • Zachowaj kod z części 1: Hook save_post_product powinien pozostać na stałe

Podsumowanie

Dodaj do pliku functions.php na stałe:

  • Hook automatycznego oznaczania kategorii nadrzędnych (część 1)

Uruchom raz i usuń:

  • Skrypt normalizacji (część 2)

Oczekiwane rezultaty:

  • Filtrowanie według kategorii nadrzędnej działa poprawnie
  • Filtrowanie według kategorii podrzędnej nadal działa
  • Zagłębianie się w hierarchię działa prawidłowo
  • Przyszłe produkty automatycznie zawierają kategorie nadrzędne