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 ActionslubSECzwraca: Brak wyników - Filtrowanie według
Enforcementzwraca: 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
- Przejdź do strony edycji produktu:
wp-admin/post.php?post=YOUR_PRODUCT_ID&action=edit - Spójrz na metabox Kategorie po prawej stronie
- Sprawdź, czy wszystkie kategorie nadrzędne w hierarchii są zaznaczone
- 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:
- Poprawka na przyszłość: Automatyczne oznaczanie kategorii nadrzędnych podczas zapisywania produktów
- 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ć:
- Dodaj kod do swojego pliku
functions.php - Przejdź do:
https://yoursite.com/?normalize_cats=1(musisz być zalogowany jako administrator) - Poczekaj na zakończenie skryptu
- Zobaczysz wyniki pokazujące, ile produktów zostało zaktualizowanych
- 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:
- Przejdź do strony sklepu z filtrami HUSKY
- Spróbuj filtrować według kategorii nadrzędnej
- Produkty z kategorii podrzędnych powinny się teraz pojawić
- 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:
- Zmiana struktury danych: To modyfikuje podstawowe relacje danych WooCommerce
- Nieuniwersalne: Niektóre witryny celowo przypisują tylko kategorie podrzędne ze względu na określoną logikę biznesową
- Wydajność: Przy bardzo dużych katalogach dodaje to narzutu przy każdym zapisie produktu
- 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:
- Edytuj każdy produkt
- W metaboxie Kategorie zaznacz ręcznie wszystkie odpowiednie kategorie nadrzędne
- 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_productpowinien 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