Search code examples
phpwordpresswoocommercestockproduct-variations

Get the count of "in stock" product variations for a variable product in Woocommerce


I'm trying to make a snippet for functions.php file that shows only one price of selected variation, thus omitting the price range displayed along with variation price on single product page. I'm using the following code:

    add_action( 'woocommerce_before_single_product', 'my_remove_variation_price' );
$product_variations=$product_variable->get_available_variations;
function my_remove_variation_price() {
  global $product;
  if ( $product->is_type( 'variable' ) {
    remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price' );
  }
}

The problem is when you have, for instance, two variations of single product and one goes out of stock, this script hides the price of one remaining variation on single product page. I was thinking maybe to have a COUNT of available variations per product and use IF to show them using standard single product template. Or maybe you have better idea how to solve that?


Solution

  • To get the "in stock" variations count of a variable product on single product pages you can:

    1) Use only php and Woocommerce WC_Product methods:

    global $product;
    $count_in_stock = 0;
    
    if ( $product->is_type( 'variable' ) ) {
        $variation_ids = $product->get_children(); // Get product variation IDs
    
        foreach( $variation_ids as $variation_id ){
            $variation = wc_get_product($variation_id);
            if( $variation->is_in_stock() )
                $count_in_stock++;
        }
    }
    
    // Your condition
    if( $count_in_stock <= 1 ){
       // Do something
    }
    

    2) Use a SQL query with few php (quick and lighter):

    global $wpdb, $product;
    $product_id = $product->get_id();
    $count_in_stock = 0;
    
    if ( $product->is_type( 'variable' ) ) {
        $count = $wpdb->get_col("
            SELECT count(p.ID) as in_stock_count FROM {$wpdb->prefix}postmeta as pm
            INNER JOIN {$wpdb->prefix}posts as p ON pm.post_id = p.ID
            WHERE p.post_type LIKE 'product_variation' AND p.post_parent = $product_id
            AND pm.meta_key LIKE '_stock_status' AND pm.meta_value LIKE 'instock'
        ");
    
        $count_in_stock = reset($count);
    }
    
    // Your condition
    if( $count_in_stock <= 1 ){
       // Do something
    }      
    

    Both codes are tested and work.