• Resolved Masidus

    (@masidus)


    Hello,

    My main aim here is to change the Related Products display to ONLY the main category of the item which the customer is viewing.

    We run a dog prints/art site, so for example if someone is looking at greyhounds, I want the Related Products to ONLY show other items which are in the category ‘Greyhound’.

    The breed is already selected as the main category (parent) so I just want to target that and nothing else.

    I’d like to do this by editing my functions.php in the child theme as I’d like this to be permanent and not require extra plugin processing power.

    Many thanks!

Viewing 15 replies - 1 through 15 (of 21 total)
  • Hi,

    Via woocommerce_related_products hook you can adjust the query to your wishes. The following example shows, for example, how you can display related products based on the same product title.

    https://businessbloomer.com/woocommerce-custom-related-products/

    /**
     * @snippet       Get Related Products by Same Title @ WooCommerce Single
     * @how-to        Get CustomizeWoo.com FREE
     * @author        Rodolfo Melogli
     * @compatible    WooCommerce 3.8
     * @donate $9     https://businessbloomer.com/bloomer-armada/
     */
     
    add_filter( 'woocommerce_related_products', 'bbloomer_related_products_by_same_title', 9999, 3 ); 
     
    function bbloomer_related_products_by_same_title( $related_posts, $product_id, $args ) {
       $product = wc_get_product( $product_id );
       $title = $product->get_name();
       $related_posts = get_posts( array(
          'post_type' => 'product',
          'post_status' => 'publish',
          'title' => $title,
          'fields' => 'ids',
          'posts_per_page' => -1,
          'exclude' => array( $product_id ),
       ));
       return $related_posts;
    }

    You can adjust this to your needs.

    Thread Starter Masidus

    (@masidus)

    Hi crslz,

    Thank you kindly for your swift reply. My knowledge of PHP is scarce and whilst I am able to make some changes, I am working on a live production site and therefore do not have the means to test sets of code without risking breaking the environment and hence, losing sales.

    Is it possible that you could adjust this code appropriately for me by chance? As mentioned in the first post, I am looking to get Related Products of ONLY the main category of the product we are on E.G. a Dalmatian Print only shows Related Products from the Dalmatian category.

    Any help would be hugely appreciated, many thanks!

    This code works for ALL categories that include the product itself

    function my_related_products_by_same_categories( $related_posts, $product_id, $args ) {
        // get categories
        $terms = wp_get_post_terms( $product_id, 'product_cat' );
    
        // set array
        $cats_array = [];
    	
        foreach ( $terms as $term ) {
            $cats_array[] = $term->term_id;
        }
    	
        $related_posts = get_posts( array(
            'post_type' => 'product',
    	'post_status' => 'publish',
    	'posts_per_page' => -1,
    	'no_found_rows' => 1,
    	'post__not_in' => array( $product_id),
    	'tax_query' => array( 
    	    array(
    		'taxonomy' => 'product_cat',
    		'field' => 'id',
    		'terms' => $cats_array
    	    )
    	)
        ));
        return $related_posts;
    }
    add_filter( 'woocommerce_related_products', 'my_related_products_by_same_categories', 9999, 3 );

    And this ONLY for the same MAIN category

    function my_related_products_by_same_main_category( $related_posts, $product_id, $args ) {
        // get categories
        $terms = wp_get_post_terms( $product_id, 'product_cat' );
    
        // set array
        $cats_array = [];
    	
        foreach ( $terms as $term ) {
    	if ($term->parent == 0) { //check for parent terms only
    	    $cats_array[] = $term->term_id;
    	}
        }
    	
        $related_posts = get_posts( array(
            'post_type' => 'product',
    	'post_status' => 'publish',
    	'posts_per_page' => -1,
    	'no_found_rows' => 1,
    	'post__not_in' => array( $product_id),
    	'tax_query' => array( 
    	    array(
    		'taxonomy' => 'product_cat',
    		'field' => 'id',
    		'terms' => $cats_array
    	    )
    	)
        ));
        return $related_posts;
    }
    add_filter( 'woocommerce_related_products', 'my_related_products_by_same_main_category', 9999, 3 );
    • This reply was modified 6 years, 6 months ago by crslz.
    Thread Starter Masidus

    (@masidus)

    Thank you for your incredibly detailed reply!

    Unfortunately neither code is working. I have checked through for obvious errors or typos however again, PHP is not my specialty.

    I changed the line if ($term->parent == 0) { //check for parent terms only to have the value of ‘1’ and the page ceased to show any Related Products at all which suggests to me the code is working, I just can’t pin down what area isn’t working.

    Just for the sake of clarity in case I’m misinterpreting something, when I say ‘Main Category’ I mean the ‘Primary Category’ which affects the Permalink and is selected in the right hand box on the ‘Edit Product’ window where you select the categories you’d like the product to be in. Next to these boxes is a selector for you to choose ‘Primary Category’.

    Thank you so much for your time, hugely appreciated!!

    the 2nd example only works for items that contain a main category, the first example will show related products with the same category as the current product (or if the product contains multiple categories, for all those categories).

    You can also apply it as follows, but then it will only work for products that contain a main category

    function my_related_products_by_same_main_category( $related_posts, $product_id, $args ) {
        // get categories
        $terms = wp_get_post_terms( $product_id, 'product_cat' );
    
    	foreach ($terms as $term) {
    		// gets product cat id
    		$product_cat_id = $term->term_id;
    
    		// gets an array of all parent category levels
    		$product_parent_categories_all_hierachy = get_ancestors( $product_cat_id, 'product_cat' );  
    
    		// This cuts the array and extracts the last set in the array
    		$last_parent_cat = array_slice($product_parent_categories_all_hierachy, -1, 1, true);
    	}
    	
        $related_posts = get_posts( array(
            'post_type' => 'product',
    		'post_status' => 'publish',
    		'posts_per_page' => -1,
    		'no_found_rows' => 1,
    		'post__not_in' => array( $product_id),
    		'tax_query' => array( 
    			array(
    				'taxonomy' => 'product_cat',
    				'field' => 'id',
    				'terms' => $last_parent_cat
    			)
    		)
        ));
    	
        return $related_posts;
    }
    add_filter( 'woocommerce_related_products', 'my_related_products_by_same_main_category', 9999, 3 );
    Thread Starter Masidus

    (@masidus)

    Thank you again for the swift reply, however the code is still not working and I can’t decipher why.

    It’s still just displaying the normal, random selection of products.

    Many thanks!

    Maybe you should try changing the priority number?

    add_filter( 'woocommerce_related_products', 'my_related_products_by_same_main_category', 9999, 3 );

    to

    add_filter( 'woocommerce_related_products', 'my_related_products_by_same_main_category', 10, 3 );

    You can also always debug by applying print_r or var_dump to the variables, so that you can see which values ​​these contain but on a live website this is indeed not recommended. WP staging is recommended for this.

    Thread Starter Masidus

    (@masidus)

    Still no joy sadly, sorry I can’t be of anymore use!

    Thank you so much for your time so far, if you have any otehr suggestions then they would be most appreciated!

    Then the only way is debugging. Can you execute this code with a product and post the output here? afterwards you can safely remove the code again.

    The output can be found just above the related products.

    function my_related_products_by_same_categories( $related_posts, $product_id, $args ) {
        // get categories
        $terms = wp_get_post_terms( $product_id, 'product_cat' );
    
        // set array
        $cats_array = [];
    	
        foreach ( $terms as $term ) {
    	echo '<pre>', print_r($term, 1), '</pre>';
            $cats_array[] = $term->term_id;
        }
    
        echo '<pre>', print_r($cats_array, 1), '</pre>';
    	
        $related_posts = get_posts( array(
            'post_type' => 'product',
    	'post_status' => 'publish',
    	'posts_per_page' => -1,
    	'no_found_rows' => 1,
    	'post__not_in' => array( $product_id),
    	'tax_query' => array( 
    	    array(
    		'taxonomy' => 'product_cat',
    		'field' => 'id',
    		'terms' => $cats_array
    	    )
    	)
        ));
    	
        return $related_posts;
    }
    add_filter( 'woocommerce_related_products', 'my_related_products_by_same_categories', 9999, 3 );
    Thread Starter Masidus

    (@masidus)

    Amazing!

    The output is as follows –

    WP_Term Object
    (
        [term_id] => 74
        [name] => Dalmatian
        [slug] => dalmatian
        [term_group] => 0
        [term_taxonomy_id] => 74
        [taxonomy] => product_cat
        [description] => 
        [parent] => 99
        [count] => 11
        [filter] => raw
    )
    WP_Term Object
    (
        [term_id] => 72
        [name] => Prints
        [slug] => prints
        [term_group] => 0
        [term_taxonomy_id] => 72
        [taxonomy] => product_cat
        [description] => 
        [parent] => 0
        [count] => 37
        [filter] => raw
    )
    WP_Term Object
    (
        [term_id] => 137
        [name] => Large
        [slug] => large
        [term_group] => 0
        [term_taxonomy_id] => 137
        [taxonomy] => product_cat
        [description] => 
        [parent] => 72
        [count] => 9
        [filter] => raw
    )
    Array
    (
        [0] => 74
        [1] => 72
        [2] => 137
    )

    So for this product I only want the 11 products from the Dalmatian group displayed, where as in a greyhound piece for example, I only want Greyhounds displayed.

    Thank you again, you’ve already taught me a bunch which I really appreciate!

    • This reply was modified 6 years, 6 months ago by Masidus.

    Okay, so this product contains 3 categories
    – Dalmatian
    – Prints
    – Large

    Well, in the output you can see that ‘Prints’ is the main category of this product, because the parent => 0. However, “Dalmatian” and “Large” contain a parent ID
    so you cannot determine a difference between these. So it won’t work!

    The only thing you can try here is to use the first result in the array and ignore the other results.

    function my_related_products_by_same_categories( $related_posts, $product_id, $args ) {	
        // get categories
        $terms = wp_get_post_terms( $product_id, 'product_cat' );
    
        // set array
        $cats_array = [];
    	
        foreach ( $terms as $term ) {
            $cats_array[] = $term->term_id;
            break;
        }
    	
        $related_posts = get_posts( array(
            'post_type' => 'product',
    	'post_status' => 'publish',
    	'posts_per_page' => -1,
    	'no_found_rows' => 1,
    	'post__not_in' => array( $product_id),
    	'tax_query' => array( 
    	    array(
    		'taxonomy' => 'product_cat',
    		'field' => 'id',
    		'terms' => $cats_array
    	    )
    	)
        ));
    	
        return $related_posts;
    }
    add_filter( 'woocommerce_related_products', 'my_related_products_by_same_categories', 9999, 3 );
    Thread Starter Masidus

    (@masidus)

    Am I right in thinking this won’t achieve my end goal though?

    Is there anyway to isolate the subcategory if this is the case so I am able to group related products by breed?

    My issue is, if you have a dog generally 95% of people are crazy about one breed, so it’s useless us advertising anything but this breed to most.

    If you can think of any other way to achieve this that would be amazing as I need the result to be processed by WooCommerce itself and not an external plugin in order for al my systems to work correctly.

    Many thanks!

    Maybe you should add per product (one) tag that is most applicable to that product and base the code on it, so that only related products with the same tag are shown

    It is true that what you are trying to achieve will not be possible, because from your example ‘Prints’ is the main category and therefore not ‘Dalmatian’.

    Thread Starter Masidus

    (@masidus)

    Ok so if I were to change every product to just contain one tag, being the breed, what would be the code which I would use to base related products just from that single tag?

    add_filter( 'woocommerce_output_related_products_args', function( $args ) { 
        $args = wp_parse_args( array( 'posts_per_page' => 4 ), $args );
        return $args;
    });
    
    add_filter( 'woocommerce_product_related_posts_relate_by_category', function() {
        return false;
    });
Viewing 15 replies - 1 through 15 (of 21 total)

The topic ‘Related Products’ is closed to new replies.