Filtro de WooCommerce por categoría no devuelve resultados: Solución de jerarquía de categorías
Si el filtro de productos por categoría en WooCommerce no devuelve resultados para las categorías principales, aunque haya productos asignados a categorías secundarias, esta guía te ayudará a solucionarlo.
El problema
Síntoma: Al filtrar por una categoría principal, no se muestran productos, aunque existan productos en sus categorías secundarias.
Ejemplo:
- Estructura de categorías:
Federal Actions > SEC > Enforcement - Producto asignado a:
Enforcement(solo categoría secundaria) - Filtrar por
Federal ActionsoSECdevuelve: Sin resultados - Filtrar por
Enforcementdevuelve: Producto mostrado
Por qué ocurre esto
WordPress/WooCommerce requiere que los productos estén marcados explícitamente con todas las categorías principales en la jerarquía, no solo con la categoría secundaria.
Cuando asignas un producto a una categoría secundaria a través de la interfaz de administración de WordPress, WooCommerce no marca automáticamente el producto con todas las categorías principales en la tabla de relaciones de términos. Esto es un requisito de la estructura de datos, no una limitación de HUSKY.
La asignación correcta de categorías debería incluir:
- Categoría secundaria:
Enforcement - Categoría principal:
SEC - Categoría abuela:
Federal Actions
Cómo comprobar si tienes este problema
- Ve a la página de edición de un producto:
wp-admin/post.php?post=YOUR_PRODUCT_ID&action=edit - Mira la metabox de Categorías en el lado derecho
- Comprueba si todas las categorías principales de la jerarquía están marcadas
- Si solo está marcada la categoría secundaria → Tienes este problema
Solución: Normalización automática de la jerarquía de categorías
Esta solución consta de dos partes:
- Solución a futuro: Marcar automáticamente las categorías principales al guardar productos
- Solución inmediata: Normalizar todos los productos existentes
Parte 1: Marcar automáticamente las categorías principales (productos futuros)
Añade este código al functions.php de tu tema hijo:
/**
* 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);
}
}
}
Qué hace esto:
- Se activa cada vez que se guarda un producto
- Obtiene todas las categorías asignadas
- Encuentra todas las categorías principales de cada categoría asignada
- Marca el producto con la jerarquía completa
- Limpia todas las cachés relevantes
Resultado: A partir de ahora, cualquier producto guardado incluirá automáticamente todas las categorías principales.
Parte 2: Normalizar productos existentes (solución única)
Este script corregirá todos los productos existentes en tu base de datos. Añade este código temporal a tu 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
];
}
Cómo usarlo:
- Añade el código a tu
functions.php - Ve a:
https://yoursite.com/?normalize_cats=1(debes haber iniciado sesión como administrador) - Espera a que el script se complete
- Verás los resultados que muestran cuántos productos se actualizaron
- Elimina este código después de ejecutarlo una vez
Salida esperada:
Category Normalization Results
Array
(
[success] => 1
[normalized] => 156
[total] => 919
)
Esto significa que 156 productos de 919 tenían categorías principales faltantes y han sido corregidos.
Prueba de la solución
Después de implementar ambas partes:
- Ve a tu página de tienda con los filtros HUSKY
- Intenta filtrar por una categoría principal
- Los productos de las categorías secundarias ahora deberían aparecer
- Intenta profundizar en la jerarquía: todos los niveles deberían funcionar
¿Por qué no hacer esto predeterminado en HUSKY?
Es una pregunta legítima. Aquí está el motivo:
- Cambio en la estructura de datos: Esto modifica las relaciones de datos principales de WooCommerce
- No es universal: Algunos sitios asignan intencionadamente solo categorías secundarias por lógica de negocio específica
- Rendimiento: En catálogos muy grandes, esto añade sobrecarga en cada guardado de producto
- Conflictos: Puede interferir con otros plugins que gestionan las relaciones de categorías
Mejora futura: Podríamos añadir esto como una configuración opcional en HUSKY que los usuarios puedan habilitar si es necesario, pero no será el comportamiento predeterminado.
Alternativa: Asignación manual de categorías
Si prefieres el control manual, puedes:
- Editar cada producto
- En la metabox de Categorías, marca todas las categorías principales relevantes manualmente
- Guardar el producto
Esto te da un control granular pero requiere mucho tiempo para catálogos grandes.
Solución de problemas
El script muestra 0 productos normalizados
- Tus productos ya podrían tener las categorías principales asignadas correctamente
- Revisa algunos productos manualmente para verificarlo
El filtrado sigue sin funcionar después de la normalización
- Limpia todas las cachés (WordPress, servidor, navegador)
- Asegúrate de que HUSKY esté usando la taxonomía correcta (
product_cat) - Comprueba si hay conflictos con otros plugins de filtrado
- Verifica que los productos estén publicados (no en borrador)
Los productos desaparecen del filtro de categoría secundaria
Esto no debería ocurrir, pero si sucede:
- El script conserva todas las asignaciones de categorías existentes
- Comprueba si otro plugin está interfiriendo
- Restaura desde una copia de seguridad y contacta al soporte
Taxonomías personalizadas
Esta solución también funciona para taxonomías personalizadas creadas con CPT UI o plugins similares. Simplemente cambia 'product_cat' por el slug de tu taxonomía personalizada:
// 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');
Notas importantes
- Tema hijo obligatorio: Usa siempre un tema hijo para evitar la pérdida de código durante las actualizaciones del tema
- Respaldar primero: Haz una copia de seguridad de tu base de datos antes de ejecutar el script de normalización
- Probar en un entorno de pruebas: Prueba en un sitio de prueba si es posible
- Script de una sola vez: Elimina el script de normalización después de ejecutarlo
- Conservar el código de la Parte 1: El hook
save_post_productdebe permanecer de forma permanente
Resumen
Añadir a functions.php de forma permanente:
- Hook para marcar automáticamente las categorías principales (Parte 1)
Ejecutar una vez y eliminar:
- Script de normalización (Parte 2)
Resultados esperados:
- El filtrado por categoría principal funciona correctamente
- El filtrado por categoría secundaria sigue funcionando
- La navegación jerárquica funciona correctamente
- Los productos futuros incluyen automáticamente las categorías principales