skip to Main Content

I would like to show only "in stock" related products on WooCommerce single product pages.

I know I can override single-product/related.php template file via My theme. Here below is the related code for this template:

<section class="related products">

    <h2><?php _e( 'You May Also Want', 'MyStore' ); ?></h2>

    <?php woocommerce_product_loop_start(); ?>

        <?php foreach ( $related_products as $related_product ) : ?>

            <?php
                $post_object = get_post( $related_product->get_id() );

                setup_postdata( $GLOBALS['post'] =& $post_object );

                wc_get_template_part( 'content', 'product' ); ?>
                
        <?php endforeach; ?>

    <?php woocommerce_product_loop_end(); ?>

</section>

Is it possible making some changes to this file to only show "in stock" related products on WooCommerce single product page? Any help is appreciated.

3

Answers


  1. UPDATE

    Because when the 4 first products are out of stock it does not display anything (In case the default 4 products are shown) you could use the following snippet instead of overwriting the template file.

    function filter_woocommerce_related_products( $related_posts, $product_id, $args ) {    
        foreach( $related_posts as $key => $related_post ) {        
            // Get product
            $related_product = wc_get_product( $related_post );
            
            // Is a WC product 
            if ( is_a( $related_product, 'WC_Product' ) ) {
                // Stock status
                $stock_status = $related_product->get_stock_status();
                
                // NOT instock
                if ( $stock_status != 'instock' ) {
                    unset( $related_posts[$key] );
                }
            }
        }
        
        return $related_posts;
    }
    add_filter( 'woocommerce_related_products', 'filter_woocommerce_related_products', 10, 3 );
    


    Overwriting the template file

    There are always multiple solutions but 1 of them could be by overwriting the template file.

    https://github.com/woocommerce/woocommerce/blob/02cf0dfaed5923513de0c88add597d1560c2cfd2/templates/single-product/related.php

    • This template can be overridden by copying it to yourtheme/woocommerce/single-product/related.php

    Replace

    <?php foreach ( $related_products as $related_product ) : ?>
    
            <?php
            $post_object = get_post( $related_product->get_id() );
    
            setup_postdata( $GLOBALS['post'] =& $post_object ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited, Squiz.PHP.DisallowMultipleAssignments.Found
    
            wc_get_template_part( 'content', 'product' );
            ?>
    
    <?php endforeach; ?>
    

    With

    <?php foreach ( $related_products as $related_product ) : ?>
    
        <?php
        $stock_status = $related_product->get_stock_status();
    
        if ( $stock_status == 'instock' ) {
            
            $post_object = get_post( $related_product->get_id() );
    
            setup_postdata( $GLOBALS['post'] =& $post_object ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited, Squiz.PHP.DisallowMultipleAssignments.Found
    
            wc_get_template_part( 'content', 'product' );
        }
        ?>
    
    <?php endforeach; ?>
    
    Login or Signup to reply.
  2. Instead of editing template files, you can use woocommerce_product_related_posts_query dedicated filter hook to alter the query excluding "out of stock" products from displayed related products:

    add_filter( 'woocommerce_product_related_posts_query', 'alter_product_related_posts_query', 10, 3 );
    function alter_product_related_posts_query( $query, $product_id, $args ){
        global $wpdb;
    
        $query['join']  .= " INNER JOIN {$wpdb->postmeta} as pm ON p.ID = pm.post_id ";
        $query['where'] .= " AND pm.meta_key = '_stock_status' AND meta_value != 'outofstock' ";
    
        return $query;
    }
    

    Code goes in functions.php file of the active child theme (or active theme). Tested and works.

    Related: Customize related products with a custom meta query in Woocommerce

    Login or Signup to reply.
  3. This is what I’ve been using, and it works for me:

    add_filter( 'woocommerce_related_products', 'mysite_filter_related_products', 10, 1 );
    function mysite_filter_related_products( $related_product_ids )
    {
    
    if (!is_admin()) {
        foreach ($related_product_ids as $key => $value) {
            $relatedProduct = wc_get_product($value);
            if (!$relatedProduct->is_in_stock() ) {
                unset($related_product_ids["$key"]);
            }
        }
    
        return $related_product_ids;
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search