Home  >  Q&A  >  body text

Select woocommerce related products using custom taxonomy with 3 level hierarchy

I have a woocommerce store with a custom category of "Sports". The classification has three levels - parent, child, child - for example: Indoor Sports > Arena Sports > Basketball. If the user views the Basketball item, then I want the related products to show other Basketball items first, and then fall back to the Arena Sport item if there aren't enough Basketball items. So, the lowest level is checked first - Sub-Child, then Child, then Parent.

Also, I use RankMath and I can set the classification term as the "primary" term. So, in the example above, the main term is basketball. Main terms are almost always sub-sub-terms, but may also be sub-terms.

I combined the answers from the other two questions and the code works by selecting relevant products from the sports category. But it only looks at sub-levels, not sub-sub-levels. So, in the example above, it selects the items in Arena Sports without prioritizing Basketball.

What changes should I make to ensure that related products see the "main" taxonomy term and then look for products with that term first, and then (if necessary) the next level down the term hierarchy?

Thanks for any help or advice you can provide.

I referred to these two articles when drafting the code:

WooCommerce Related Products by Kids Category as Backup to Rank Math Primary Category

Select related products in Woocommerce using custom taxonomies

This is the code I'm currently using:

add_filter( 'woocommerce_related_products', 'related_products_from_rankmath_primary_esporte_taxonomy', 10, 3 );
    function related_products_from_rankmath_primary_esporte_taxonomy( $related_posts, $product_id, $args ) {
        $taxonomy     = 'sport'; 
        $term_ids     = wp_get_post_terms( $product_id, $taxonomy, array( 'fields' => 'ids' ) ); 
        $term_slugs   = array(); 
  
 if( count($term_ids) == 1 ) {
        // Get children categories
        $children_ids = get_term_children( reset($category_ids), $taxonomy );
        // Loop through children terms Ids
        foreach ( $children_ids as $tem_id ) {
            $term_slugs[] = get_term_by( 'id', $tem_id, $taxonomy )->slug; // get the slug from each term Id
        }
    } 
    elseif( count( $term_ids ) > 1 ) {
        // Get the primary taxonomy/term as saved by Rank Math SEO
        $primary_tax_id = get_post_meta( $product_id, 'rank_math_primary_taxonomy', true );
        $term_slugs[]   = get_term_by( 'id', $primary_tax_id, $taxonomy )->slug; // get the slug from the term Id
    }
        
        
        if ( count( $term_ids ) > 0 ) {
            foreach ( $term_ids as $term_id ) {
                $term_slugs[] = get_term_by( 'id', $term_id, $taxonomy )->slug; 
    
                // Gets the IDs of child terms
                $children_ids = get_term_children( $term_id, $taxonomy );
    
                foreach ( $children_ids as $child_id ) {
                    $term_slugs[] = get_term_by( 'id', $child_id, $taxonomy )->slug; // Gets the slug of each child term
                }
            }
   
   
            $related_posts = wc_get_products( array(
                'status'        => 'publish',
                'tax_query'     => array(
                    array(
                        'taxonomy' => $taxonomy,
                        'field'    => 'slug',
                        'terms'    => $term_slugs,
                    ),
                ),
                'return'        => 'ids',
                'exclude'       => array( $product_id ),
                'visibility'    => 'catalog',
                'limit'         => -1,
            ) );
        }

    
    
        return $related_posts;
    }

P粉037215587P粉037215587154 days ago490

reply all(1)I'll reply

  • P粉029327711

    P粉0293277112024-04-07 14:00:50

    Try the following (commented):

    // Utility function: Get related product Ids with a custom tax query
    function get_related_posts_custom_query( $term_slugs, $taxonomy, $product_id ) {
        return wc_get_products( array(
            'limit'         => -1,
            'status'        => 'publish',
            'exclude'       => array( $product_id ),
            'visibility'    => 'catalog',
            'tax_query'     => array(
                array(
                    'taxonomy' => $taxonomy,
                    'field'    => 'slug',
                    'terms'    => $term_slugs,
                ),
            ),
            'return'        => 'ids',
        ) );
    }
    
    add_filter( 'woocommerce_related_products', 'related_products_from_rank_math_primary_category', 10, 3 );
    function related_products_from_rank_math_primary_category( $related_posts, $product_id, $args  ) {
        // Get product categories set for the product
        $category_ids = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids') ); 
        $term_slugs   = array(); // Initializing   
    
        // 1). Only one product category => Fallback (Query products from "Sport" taxonomy)
        if( count($category_ids) == 1 ) {
            $taxonomy      = 'sport';
            // Get "Sport" the term set in the product
            $sport_ids     = wp_get_post_terms($product_id, $taxonomy, array('fields' => 'ids') ); 
            $term          = get_term_by( 'id', reset($sport_ids), $taxonomy );
            $term_slugs[]  = $term ->slug;
            // Get related products from the "Sport" term
            $related_posts = get_related_posts_custom_query( $term_slugs, $taxonomy, $product_id );
    
            // IF there is not enough related products: Add the CHILDREN terms
            if ( $related_posts < 6 ) {
                $children_ids = get_term_children( reset($sport_ids), $taxonomy );
                if( count($children_ids) > 0 ) {
                    foreach ( $children_ids as $tem_id ) {
                        $term_slugs[] = get_term_by( 'id', $tem_id, $taxonomy )->slug; // get the slug from each term Id
                    }
                    // Get related products from the "Sport" terms
                    $related_posts = get_related_posts_custom_query( $term_slugs, $taxonomy, $product_id );
                }
                // IF there is not enough related products: Add the PARENT term
                if ( $related_posts < 6 ) {
                    $parent       = get_term_by( 'id', $term->parent, $taxonomy );
                    $term_slugs[] = $parent ->slug;
                    // Get related products from the "Sport" terms
                    return get_related_posts_custom_query( $term_slugs, $taxonomy, $product_id );
                } else {
                    return $related_posts;
                }
            } else {
                return $related_posts;
            }
        } 
        // 2). More than one product categories => Rank Math SEO
        elseif( count( $category_ids ) > 1 ) {
            // Get the primary category/term as saved by Rank Math SEO
            $primary_cat_id = get_post_meta( $product_id, 'rank_math_primary_product_cat', true );
            $taxonomy       = 'product_cat';
            $term_slugs[]   = get_term_by( 'id', $primary_cat_id, $taxonomy )->slug; // get the slug from the term Id
            // Get related products from the category terms via Rank Math SEO
            return get_related_posts_custom_query( $term_slugs, $taxonomy, $product_id );
        }
        return $related_posts;
    }
    

    It should work.

    reply
    0
  • Cancelreply