Hide out of stock related products in WooCommerce
Asked Answered
R

7

8

In WooCommerce I would like to hide Out of Stock products from Related products in single product pages. Is it possible?

Any track is appreciated.

Rover answered 1/3, 2019 at 20:29 Comment(0)
A
6

UPDATE 2021

You can use the following:

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 = 'instock' ";
    
    return $query;
}

Code goes in functions.php file of your active child theme (or active theme).

Now we need to remove "related products" cached data deleting the related transients to flush this cache (thanks to @Cody Rees).

There is 2 ways to do it:

1). The easiest way:

Go to admin Woocommerce > Status > Tools > WooCommerce transients and press on "Clear transcients".

2). The other way targeting specific related transients to be deleted:

Add the following code and save:

add_action('init', 'delete_related_products_cached_data');
function delete_related_products_cached_data() {
    global $wpdb;

    $wpdb->query("DELETE FROM {$wpdb->prefix}options WHERE `option_name` LIKE '_transient_wc_related_%'");
}

Code goes in functions.php file of your active child theme (or active theme).

Run it only once by browsing any page of your web site and remove it.

Augie answered 1/3, 2019 at 20:46 Comment(7)
I really appreciate your help : But It doesn't work ; I've cleared the cache but I didn't see any change.Rover
I know your code is correct; But I don't know why nothing happen to my site!!! I've changed so many times this code! But I didn't see any change! What's wrong?Rover
@sarahmiller I haven't anything better for instance.Augie
It doesn't work with backorder products. They are shown despite the _stock_status = instockSmashing
Answer has been updated thanks to @CodyReesAugie
Your solution is not working. I applied the 2021 update and then cleared the transient cache data but it still doesn't workYeseniayeshiva
@Yeseniayeshiva for me and for CodyRees it works… So maybe something else is making trouble in your case…Augie
B
14

None of the answers given here worked for me (I believe the woocommerce_output_related_products_args filter mentioned does not accept meta_queries), and I wanted a solution that didn't use an SQL query, so I put together the solution below:

add_filter( 'woocommerce_related_products', 'mysite_filter_related_products', 10, 1 );
function mysite_filter_related_products( $related_product_ids ) {

    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;
}

Hope that helps someone looking for a similar solution.

Brummell answered 1/4, 2020 at 18:4 Comment(4)
+1 but this using this solution will not replace the removed related products with other related products, so you'll end up with less than the number of related products you wanted. E.g. if you want 4 to always display, but a particular product's related products contain 2 out of stock products, then only 2 related products will display.Truant
To fix that, one could add more code, before the return, to check for the count of $related_product_ids and query for some more products, if the count is less than the desired number.Truant
Doesn't work either for the latest versions of woocommerce. The filter woocommerce_related_products doesn't only receive the $related_products_idsargument.Yeseniayeshiva
It works, Thanks dmoz and sarah miller.Samaveda
A
6

UPDATE 2021

You can use the following:

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 = 'instock' ";
    
    return $query;
}

Code goes in functions.php file of your active child theme (or active theme).

Now we need to remove "related products" cached data deleting the related transients to flush this cache (thanks to @Cody Rees).

There is 2 ways to do it:

1). The easiest way:

Go to admin Woocommerce > Status > Tools > WooCommerce transients and press on "Clear transcients".

2). The other way targeting specific related transients to be deleted:

Add the following code and save:

add_action('init', 'delete_related_products_cached_data');
function delete_related_products_cached_data() {
    global $wpdb;

    $wpdb->query("DELETE FROM {$wpdb->prefix}options WHERE `option_name` LIKE '_transient_wc_related_%'");
}

Code goes in functions.php file of your active child theme (or active theme).

Run it only once by browsing any page of your web site and remove it.

Augie answered 1/3, 2019 at 20:46 Comment(7)
I really appreciate your help : But It doesn't work ; I've cleared the cache but I didn't see any change.Rover
I know your code is correct; But I don't know why nothing happen to my site!!! I've changed so many times this code! But I didn't see any change! What's wrong?Rover
@sarahmiller I haven't anything better for instance.Augie
It doesn't work with backorder products. They are shown despite the _stock_status = instockSmashing
Answer has been updated thanks to @CodyReesAugie
Your solution is not working. I applied the 2021 update and then cleared the transient cache data but it still doesn't workYeseniayeshiva
@Yeseniayeshiva for me and for CodyRees it works… So maybe something else is making trouble in your case…Augie
E
1

Yes it's possible to hide out of stock products from related products.

Add the below to functions.php – this will hide out of stock products from related products.

add_filter( 'woocommerce_output_related_products_args', function( $args )
{
    $args = wp_parse_args( array(
        'posts_per_page' => 4,
        'meta_query' => array (
           'key' => '_stock_status',
           'value' => 'instock'
    )
    ), $args );
    return $args;
});

The posts per page line can be removed, but its useful as a quick of visualising that this has worked on your related products block.

Elation answered 21/4, 2019 at 15:31 Comment(1)
Doesn't work, tested thoroughlyCopartner
P
1

For those who didn't find solution: Tested on Woocommerce +6

add_filter( 'woocommerce_related_products', 'vahids_related_products', 10, 3 );
function vahids_related_products( $related_posts, $product_id, $args ){
    $in_stock_product_ids = (array) wc_get_products( array(
        'status'       => 'publish',
        'limit'        => -1,
        'stock_status' => 'instock',
        'return'       => 'ids',
     ));

    return $in_stock_product_ids;
}
Preoccupied answered 29/5, 2022 at 14:1 Comment(0)
C
1

You can use the following code to hide out-of-stock related products. This code loops through the related products checks if they are in stock and removes them from the list if they aren't

    function hide_out_of_stock_related_products( $related_posts ) {
    foreach ( $related_posts as $key => $related_post_id ) {
        $product = wc_get_product( $related_post_id );
        if ( ! $product->is_in_stock() ) {
            unset( $related_posts[ $key ] );
        }
    }
    return $related_posts;
}
add_filter( 'woocommerce_related_products', 'hide_out_of_stock_related_products' );
Calve answered 29/8 at 10:30 Comment(0)
U
-1

This is working code from here. Add this code to your functions.php and you will see that our of stocks products will not be seen in related product block. Code is from here : https://mcmap.net/q/1323109/-woocommerce-related-products-only-show-in-stock-related-products

    add_filter( 'woocommerce_related_products', 'mysite_filter_related_products', 10, 1 );
function mysite_filter_related_products( $related_product_ids ) {

    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;
}
Unicef answered 4/4, 2022 at 21:28 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Brinn
F
-2

create a function and hook it to related products hook of woocommerce like:

function dont_show_outofstock( $is_visible, $id ) {
    $product = new wC_Product( $id );

    if ( ! $product->is_in_stock() && ! $product->backorders_allowed() ) {
    $is_visible = false;
    }

    return $is_visible;
}
add_filter( 'woocommerce_output_related_products_args', 'dont_show_outofstock', 10, 2 );
Fiedler answered 2/3, 2019 at 10:5 Comment(2)
It crashed my site and after adding this snippet I don't see related products and also footer of the page!!!Rover
That filter doesn't take/pass those argumentsTruant

© 2022 - 2024 — McMap. All rights reserved.