skip to Main Content

I use the built in WooCommerce filter by attribute widget which works for what I need, but my issue is, that if I filter on a size, I get all products with that size as an attribute, also when they are out of stock…

My products are created as a variable product with variations on size and color

What I want, is to filter a size and only display products in that size that is in stock.

4

Answers


  1. You can hide out of stock products by checking the option of "Out of stock visibility" on the Settings page:

    Woocommerce > Settings > Product > Inventory

    Login or Signup to reply.
  2. It may not be possible for variable products and their variations (but only for other product types).

    It can only works for variable products when stock management is handled by the product variation itself (but not by the variations).

    Note that WooCommerce product query doesn’t handle post type ‘product_variation’, but only post type ‘product’.

    To exclude out of stock products using widget filters (except for variable products) you can use:

    add_filter( 'woocommerce_product_query_tax_query', 'filter_product_query_tax_query' );
    function filter_product_query_tax_query( $tax_query ){
        if ( ! is_admin() && isset($_GET['filter_color']) && ! empty($_GET['filter_color']) ) {
            // Exclude products "out of stock"
            $tax_query[] = array(
                'taxonomy' => 'product_visibility',
                'field'    => 'name',
                'terms'    => array('outofstock'),
                'operator' => 'NOT IN'
            );
        }
    
        return $tax_query;
    }
    

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

    Login or Signup to reply.
  3. I’ve used this code for my stores to hide product sizes that are not in stock whilst filtering.

    add_filter( 'woocommerce_product_is_visible', 'hide_product_with_outofstock_variation', 10, 2 );
    if(!function_exists('hide_product_with_outofstock_variation')){
        function hide_product_with_outofstock_variation( $is_visible, $id ) {
            $product = wc_get_product($id);
            if ( $product->is_type('variable')) { // if variation product is out of stock
                $available = $product->get_available_variations();
                if ( $available )foreach ( $available as $instockvar ) {
                    if(isset($_GET['filter_size'])){
                        $destostock = $_GET['filter_size'];
                        if($destostock ==$instockvar['attributes']['attribute_pa_size']){
                            if($instockvar['is_in_stock']){
                                $is_visible = true;
                            }else{
                                $is_visible = false;
                            }
                        }
                    }
                }
            }
            return $is_visible;
        }
    }
    
    Login or Signup to reply.
  4. filter_size will be converted in array if many filter being selected.
    As for product variations, best if its stored in an array as well and use array_intersect to search if one of the selected item available in stock.

    add_filter( 'woocommerce_product_is_visible', 'hide_product_with_outofstock_variation', 10, 2 );
    if(!function_exists('hide_product_with_outofstock_variation')){
        function hide_product_with_outofstock_variation( $is_visible, $id ) {
            if(isset($_GET['filter_size'])){
                    $filter_size = explode(',',$_GET['filter_size']);
                    $product = wc_get_product($id);
                    if ( $product->is_type('variable')) { // if variation product is out of stock
                        $available = $product->get_available_variations();
                        $available_size = array();
    
                        if ( $available )foreach ( $available as $instockvar ) {
                            array_push($available_size, $instockvar['attributes']['attribute_pa_size']);
                        }
                        if (count(array_intersect($filter_size, $available_size)) === 0) {
                            $is_visible = false;
                        }else{
                            $is_visible = true;
                        }
                    }
            }
            return $is_visible;
        }
    }
    

    This code works for me

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search