Productos relacionados sólo de la subcategoría actual en WooCommerce

En este artículo vemos como modificar los productos relacionados de WooCommerce para que se muestren sólo de la misma subcategoría de productos.


por

Por defecto, los productos relacionados que aparecen en las fichas de producto con WooCommerce, se muestran de forma automática y aleatoria en función de la categoría y etiquetas del producto en el que estemos.

En otro artículo, veíamos como cambiar algunas de las características de estos productos relacionados, como modificar el número de productos, las columnas, o desactivar que se relacionaran por etiqueta y/o categoría.

Hoy vamos a ver otra duda muy común y es que se muestren sólo como relacionados los productos de la misma subcategoría del actual.

Aunque se pueden encontrar muchos códigos y snippets por la red, a mi sólo me han funcionado dos formas de hacerlo, una modificando el hook woocommerce_product_related_posts y otra, modificando el template related.php y subiéndolo a nuestro theme hijo.

 

Nota: aunque ambos son correctos, siempre es preferible modificar las funciones y hooks y no los archivos de la plantilla, pero en este caso explico ambas formas porque la primera en algún caso no me ha funcionado, tal vez por la combinación con algún theme, plugin o extensión en concreto.

 

Opción 1: modificando woocommerce_product_related_posts

En principio sería la forma más correcta de hacerlo, y de todos los snippets que he probado sólo hay uno que me funciona correctamente que os pongo a continuación:

 

// Obtener productos relacionados de la misma subcategoria
add_filter( 'woocommerce_product_related_posts', 'esl_productos_relacionados' );
function esl_productos_relacionados($product){
    global $woocommerce;
    // Related products are found from category and tag
    $tags_array = array(0);
    $cats_array = array(0);
    // Get tags
    $terms = wp_get_post_terms($product->id, 'product_tag');
    foreach ( $terms as $term ) $tags_array[] = $term->term_id;
    // Get categories
    $terms = wp_get_post_terms($product->id, 'product_cat');
    foreach ( $terms as $key => $term ){
        $check_for_children = get_categories(array('parent' => $term->term_id, 'taxonomy' => 'product_cat'));
        if(empty($check_for_children)){
            $cats_array[] = $term->term_id;
        }
    }
    // Don't bother if none are set
    if ( sizeof($cats_array)==1 && sizeof($tags_array)==1 ) return array();
    // Meta query
    $meta_query = array();
    $meta_query[] = $woocommerce->query->visibility_meta_query();
    $meta_query[] = $woocommerce->query->stock_status_meta_query();
    $meta_query   = array_filter( $meta_query );
    // Get the posts
    $related_posts = get_posts( array(
            'orderby'        => 'rand',
            'posts_per_page' => $limit,
            'post_type'      => 'product',
            'fields'         => 'ids',
            'meta_query'     => $meta_query,
            'tax_query'      => array(
                'relation'      => 'OR',
                array(
                    'taxonomy'     => 'product_cat',
                    'field'        => 'id',
                    'terms'        => $cats_array
                ),
                array(
                    'taxonomy'     => 'product_tag',
                    'field'        => 'id',
                    'terms'        => $tags_array
                )
            )
        ) );
    $related_posts = array_diff( $related_posts, array( $product->id ), $product->get_upsells() );
    return $related_posts;
}

Este snippet de código deberás añadirlo al archivo functions.php de tu tema hijo, en un plugin para snippets de código o en un plugin personalizado.

 

Opción 2: modificar la plantilla related.php

Si por alguna razón el código anterior no te funcionara bien, otra opción es modificar el archivo de plantilla related.php para cambiar la query o la consulta a la base de datos que  muestra estos productos relacionados.

Este archivo se encuentra en la carpeta wp-content/plugins/woocommerce/templates/single-product/related.php y deberemos descargarlo, modificarlo y subirlo a wp-content/themes/nuestro-child-theme/woocommerce/single-product/related.php

(Fíjate que hemos de reproducir la misma estructura de carpetas/subcarpetas pero omitiendo /templates)

En este archivo, sustituiremos el contenido por el siguiente:

if (!defined('ABSPATH')) {
    exit;
}
global $post, $product;
if (empty($product) || !$product->exists()) {
    return;
}
$subcategories_array = array(0);
$all_categories = wp_get_post_terms($product->id, 'product_cat');
foreach ($all_categories as $category) {
    $children = get_term_children($category->term_id, 'product_cat');
    if (!sizeof($children)) {
    $subcategories_array[] = $category->term_id;
    }
}
if (sizeof($subcategories_array) == 1) {
    return array();
}
$args = array(
    'orderby' => 'rand',
    'posts_per_page' => 3,
    'post_type' => 'product',
    'fields' => 'ids',
    'meta_query' => $meta_query,
    'tax_query' => array(
    array(
        'taxonomy' => 'product_cat',
        'field' => 'id',
        'terms' => $subcategories_array
    )
    )
);
 
$wp_query = new WP_Query($args);
 
 
 if ($wp_query->have_posts()):
    ?>
    <section class="related products">
    <h2><?php esc_html_e('Related products', 'woocommerce'); ?></h2>
    <?php woocommerce_product_loop_start(); ?>
    <?php while ($wp_query->have_posts()) : $wp_query->the_post(); ?>
        <?php
        global $post, $product;
        $post_object = get_post($product->get_id());
        setup_postdata($GLOBALS['post'] = & $post_object);
        wc_get_template_part('content', 'product');
        ?>
    <?php endwhile; ?>
    <?php woocommerce_product_loop_end(); ?>
    </section>
    <?php
endif;

wp_reset_postdata();

En este ejemplo, el post_per_page está en 3, son el número de productos relacionados que aparecerán, y podemos modificarlo por el que queramos.

 

Como indicaba antes, ambas formas son válidas, pero yo recomiendo utilizar la primera a menos que no nos funcione y no logremos detectar el porqué.

 

Recuerda que en este artículo: Modificar los productos relacionados en WooCommerce, tienes otros cambios más sencillos si sólo quieres que no se relacionen por etiquetas o categorías o cambiar el número de productos que aparecen.

 

 

¿Eres implementador o desarrollador WordPress?

En la Zona DPW encontrarás más recursos, tutoriales, plantillas, y una biblioteca de snippets para poder utilizar en tu día a día y ganar tiempo en tu trabajo:

ACCEDER AHORA

Comentarios

16 respuestas a «Productos relacionados sólo de la subcategoría actual en WooCommerce»

  1. Avatar de joh2049

    |

    El primer método no ha funcionado en la tienda de un cliente con el tema «Avada» instalado. Sin embargo, el segundo método si ha funcionado bien.

    Probaré el primer método con dos clientes más. Uno con Storefront y otro con otra plantilla de ThemeForest (Jupiter) y cuento que tal me fue.

    Muchas gracias por el contenido y un saludo.

    PD: Avada y Jupiter no los he instalado yo, solo les llevo el mantenimiento a estos clientes jaja.

    1. Avatar de esther

      |

      jajaja, no tienes porque disculparte, yo también llevo mantenimientos de Avadas y cosas peores 😉
      Ok! Ya me dirás a ver si en los otros te funciona.

      Saludos!

  2. Avatar de Jonathan Cruz

    |

    Holaa!

    Espero estés muy bien.
    Tengo una pregunta muy puntual:
    ¿Es posible (utilizando el método 2) definir a que subcategorías quiero que afecte el filtro?

    Tengo más de 25 subcategorías pero únicamente me interesa aplicar esto a unas 5 o 6
    Supongo que con un array o algo, pero estoy muy crudo interpretando estos códigos aún y no se bien donde tocar

    Un saludo!!

    1. Avatar de esther

      |

      Hola Jonathan!
      ¿Lo que necesites es que este filtro sólo se aplique en algunos productos en concreto y no en todos? O modificar de que subcategorías debe mostrar los productos relacionados?
      Si es lo primero, podrías añadir un condicional al crear la query para modificarlo según quieras que coja las subcategorías o no.
      (escríbeme por email si quieres y lo comentamos)

      Un saludo!

  3. Avatar de Cesar

    |

    Hola, buscando cómo solucionar este problema he llegado hasta aquí, pero ninguno de los dos métodos me funciona. Si uso el método 2, me desconfigura incluso la ficha del producto. Uso el tema CERATO, de themeforest.

    1. Avatar de esther

      |

      Hola Cesar,
      Es posible que el tema ya esté modificando algunas plantillas de WooCommerce, por eso se te desconfigura con la segunda opción. También si tiene usa el mismo filtro o hook es posible que interfiera en este código. Me temo que no conozco el theme que comentas y no te puedo ayudar más…

      Saludos!

  4. Avatar de eric

    |

    hola Esther primer felicitarte por tu blog es una auténtica pasada.

    Segundo ahí va mi duda.

    Cómo puedo poner para todos los productos unos relacionados concretos? Es decir imaginate que tienes un restaurante con varias categorías( pizzas,burger,etc) y quiero que en todas estas categorías me aparezcan unos productos relacionados de la categoría bebidas.

    Por lo tanto quiero que productos relacionados siempre sean productos de la categoría bebidas.

    gracias y saludos

    1. Avatar de esther

      |

      Muchas gracias Eric!

      En el caso que comentas, creo que se podría configurar para que se relacionaran por etiqueta, no por subcategoría como comento en este post. Mírate este otro a ver si te sirve: https://www.esthersola.com/modificar-productos-relacionados-woocommerce/

      Saludos!

  5. Avatar de Jose

    |

    Hola si esta ruta no existe en mi sitio: wp-content/themes/nuestro-child-theme/woocommerce/single-product/related.php

    debo crearla?? lo intente y me dio error el sitio esto aun funciona?

    1. Avatar de esther

      |

      Hola Jose,
      Sí, el código todavía es válido. Es normal que no exista la ruta en tu sitio, has de crear tu las carpetas /woocommerce/single-product en tu child theme y subir el archivo related.php con las modificaciones pertinentes.

      Cualquier duda me dices,
      Saludos!

  6. Avatar de David

    |

    Hola Esther, muchas gracias por el aporte, na, a mi no me funciona ninguno de los dos métodos, utilizo el tema Flatsome para una tienda de discos y cómics, y claro, los quiero relacionar por estilos, que serían las subcategorías, no simplemente por discos o cómics..
    Na, no sé, eso no me funciona ninguna de las dos opciones.

    1. Avatar de esther

      |

      Hola David,
      Imagino que habrá algún conflicto con algún script de la plantilla… ¿has probado de hacerlo con un plugin?

      Saludos,

      1. Avatar de David

        |

        Hola Esther!
        Al final lo hice por etiqueta que ya me está bien.
        Muchísimas gracias!

        1. Avatar de esther

          |

          Genial! Gracias a ti David por pasarte.

  7. Avatar de ivan

    |

    Gracias por el post 😉

    Lo que no termino de entender bien del código es lo que pone:
    esl_productos_relacionados

    de donde sale ese nombre?? o no importa demasiado, ya que en otro lugar, vi el mismo código pero ponía:
    my_custom_related_products

    Quizás ese sea el punto??? ya que a mi no me ha funcionado ninguna de las maneras ;(

    Saludos

  8. Avatar de Ignacio Tröndle

    |

    Gracias!! La 2da opción me sirvió!!
    No tengo ninguna pregunta, sólo quería agradecer.