Як виправити фільтрацію ієрархії категорій у магазині woocommerce (нормалізувати базу даних)
Якщо ви стикаєтеся з проблемами, коли фільтрація за батьківськими категоріями не дає результатів, хоча товари призначені для дочірніх категорій, цей посібник допоможе вам це виправити.
Проблема
Симптом: При фільтрації за батьківською категорією товари не відображаються, хоча вони існують у її дочірніх категоріях.
Приклад:
- Структура категорії:
Federal Actions > SEC > Enforcement - Товар призначений для:
Enforcement(тільки дочірня категорія) - Фільтрація за
Federal ActionsабоSECповертає: Немає результатів - Фільтрація за
Enforcementповертає: Показаний продукт
Чому це відбувається
WordPress/WooCommerce вимагає продукти, які повинні бути явно позначені усі батьківські категорії в ієрархії, а не тільки дочірню категорію.
Коли ви призначаєте товар до дочірньої категорії через інтерфейс адміністратора WordPress, WooCommerce не позначає товар автоматично всіма батьківськими категоріями в таблиці зв'язків термінів. Це вимога структури даних, а не обмеження HUSKY.
Правильне призначення категорії має включати:
- Дочірня категорія:
Enforcement - Батьківська категорія:
SEC - Батьківська категорія:
Federal Actions
Як перевірити, чи є у вас ця проблема
- Перейдіть на сторінку редагування товару:
wp-admin/post.php?post=YOUR_PRODUCT_ID&action=edit - Подивіться на метабокс Категорії праворуч
- Перевірити, чи усі батьківські категорії в ієрархії перевіряються
- Якщо вибрано лише дочірню категорію → Ви маєте цю проблему
Рішення: Автоматична нормалізація ієрархії категорій
Це рішення складається з двох частин:
- Майбутньозахищене виправлення: Автоматично позначати батьківські категорії при збереженні товарів
- Негайна виправлення: Нормалізувати всі існуючі товари
Частина 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
];
}
Як використовувати:
- Додайте код до вашого
functions.php - Перейти до:
https://yoursite.com/?normalize_cats=1(потрібно увійти як адміністратор) - Дочекайтеся завершення скрипта
- Ви побачите результати, що показують, скільки товарів було оновлено
- Видаліть цей код після одноразового запуску
Очікуваний вивід:
Category Normalization Results
Array
(
[success] => 1
[normalized] => 156
[total] => 919
)
Це означає, що 156 товарів з 919 не мали батьківських категорій і були виправлені.
Тестування виправлення
Після реалізації обох частин:
- Перейдіть на сторінку свого магазину з фільтрами HUSKY
- Спробуйте фільтрувати за батьківська категорія
- Тепер товари з дочірніх категорій мають з'являтися
- Спробуйте проаналізувати ієрархію – усі рівні повинні працювати
Чому б не зробити це за замовчуванням у HUSKY?
Це обґрунтоване питання. Ось чому:
- Зміна структури даних: Це модифікує основні зв'язки даних WooCommerce
- Не універсальний: Деякі сайти навмисно призначають лише дочірні категорії для певної бізнес-логіки
- Продуктивність: У дуже великих каталогах це додає навантаження на кожне збереження товару
- Конфлікти: Може конфліктувати з іншими плагінами, які керують зв'язками категорій
Майбутнє вдосконалення: Можливо, ми додамо це як необов'язкове налаштування в HUSKY, що користувачі можуть увімкнути, якщо це необхідно, але це не буде поведінкою за замовчуванням.
Альтернатива: Ручне призначення категорій
Якщо ви віддаєте перевагу ручному керуванню, ви можете:
- Редагувати кожен продукт
- У метабоксі Категорії, поставте галочку усі відповідні батьківські категорії вручну
- Зберегти товар
Це дає вам детальний контроль, але вимагає багато часу для великих каталогів.
Виправлення проблем
Скрипт показує 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');
Важливі примітки
- Необхідна дочірня тема: Завжди використовуйте дочірню тему, щоб запобігти втраті коду під час оновлення теми
- Спочатку зробіть резервну копію: Резервно збережіть вашу базу даних перед запуском скрипта нормалізації
- Тестування на стейджингу: Спочатку протестуйте на тестовому сайті, якщо це можливо
- Одноразовий скрипт: Видалити скрипт нормалізації після його запуску
- Зберегти код Частини 1: The
save_post_productхук повинен залишатися постійно
Підсумок
Додайте до functions.php назавжди:
- Хук автоматичного позначення батьківських категорій (Частина 1)
Запустити один раз і видалити:
- Скрипт нормалізації (Частина 2)
Очікувані результати:
- Фільтрація за батьківською категорією працює коректно
- Фільтрація дочірніх категорій продовжує працювати
- Ієрархічні функції розгортання працюють належним чином
- Майбутні товари автоматично включають батьківські категорії