Taghi Khavari
Taghi Khavari

Reputation: 6582

How can I get Min and Max price of a woocommerce variable product in Custom loop?

I've created a custom rest route in Wordpress which takes a product category id and will send products which are in that category.

My Problem is I can't figure out a way to get variable product min and max prices inside my custom loop.

Can anyone help me with this issue? Thanks

I've tried to get variation price using get_variation_prices() but it seems that I'm missing something.

add_action( 'rest_api_init' , 'wt_rest_api'); 
function wt_rest_api(){
   register_rest_route('wtrest','products',array(
           'methods'   => WP_REST_SERVER::READABLE,
           'callback'  => 'wtProductResults'
       )); 
} 

function wtProductResults($data){
    $products = new WP_Query([
           'post_type' => 'product',
           'tax_query' => array(
                               array(
                                   'taxonomy' => 'product_cat',
                                   'field' => 'term_id', //can be set to ID
                                   'terms' => $data['cat'] //if field is ID you can reference by cat/term number
                               )
                           )
        ]);

    $productsResults = [];
    global $woocommerce;
    global $product;
   $currency = get_woocommerce_currency_symbol();

    while($products->have_posts()){
        $products->the_post();
        $product_cat = get_term(  $data['cat'], 'product_cat', 'category', "OBJECT" );
        $regularPrice = get_post_meta( get_the_ID(), '_regular_price', true);
        $sale = get_post_meta( get_the_ID(), '_sale_price', true);
        $price = get_post_meta( get_the_ID(), '_price', true );
        array_push($productsResults , [
               'title' => get_the_title(),
               'productId' => get_the_id(),
               'permalink' => get_the_permalink(),
               'thumbnail' => get_the_post_thumbnail(),
               'excerpt' => get_the_excerpt(),
               'regularPrice' => $regularPrice,
               'price'     => $price,
               'salePrice' => $sale,
               'category' => $product_cat->name,
               'variationPrice' => get_variation_prices()//**Here is My problem**
            ]);
    }
    wp_reset_postdata();    
    return $productsResults;

}

Here is my Code and when I used get_variation_prices() I didn't get any response from my rest route

Upvotes: 4

Views: 16342

Answers (3)

LoicTheAztec
LoicTheAztec

Reputation: 253921

The function get_variation_prices() is a method of WC_Product_Variable Class and it works exclusively as a method on a variable product instance object. It gives a multi dimensional array of all variations prices.

To get Min and Max variation prices, you have to use WC_Product_Variable methods:

  • get_variation_regular_price() or get_variation_regular_price('max')
  • get_variation_sale_price() or get_variation_sale_price('max')
  • get_variation_price() or get_variation_price('max')

Now in your code:

  • you will need first to get the WC_Product instance object.
  • check products type.
  • remove global $product; as it's empty and not useful.
  • (you might need to make other changes, based on your requirements)

Now there is multiple ways to query products:

1) Using a WP_Query (just as you are doing actually):

function wtProductResults($data){
    global $woocommerce;
    
    $products = new WP_Query([
       'post_type' => 'product',
       'tax_query' => array( array(
            'taxonomy' => 'product_cat',
            'field' => 'term_id', //can be set to ID
            'terms' => $data['cat'] //if field is ID you can reference by cat/term number
        ) )
    ]);
    
    $productsResults = [];
    $currency        = get_woocommerce_currency_symbol();
   
    if ( $products->have_posts() ) :
    while ( $products->have_posts() ) : $products->the_post();
    
    $product_cat = get_term(  $data['cat'], 'product_cat', 'category', "OBJECT" );
        
    // Get an instance of the WC_Product object
    $product = wc_get_product( get_the_ID() );
    
    if( $product->is_type('variable') ) {
        // Min variation price
        $regularPriceMin = $product->get_variation_regular_price(); // Min regular price
        $salePriceMin    = $product->get_variation_sale_price(); // Min sale price
        $priceMin        = $product->get_variation_price(); // Min price
    
        // Max variation price
        $regularPriceMax = $product->get_variation_regular_price('max'); // Max regular price
        $salePriceMax    = $product->get_variation_sale_price('max'); // Max sale price
        $priceMax        = $product->get_variation_price('max'); // Max price
    
        // Multi dimensional array of all variations prices 
        $variationsPrices = $product->get_variation_prices(); 
        
        $regularPrice = $salePrice = $price = '';
        $variationPrice = [
            'min' => $product->get_variation_price(),
            'max' => $product->get_variation_price('max')
        ];
    } 
    // Other product types
    else {
        $regularPrice   = $product->get_regular_price();
        $salePrice      = $product->get_sale_price();
        $price          = $product->get_price(); 
        $variationPrice = ['min' => '', 'max' => ''];
    }
    
    array_push( $productsResults , [
       'title'          => get_the_title(),
       'productId'      => get_the_id(),
       'permalink'      => get_the_permalink(),
       'thumbnail'      => get_the_post_thumbnail(),
       'excerpt'        => get_the_excerpt(),
       'regularPrice'   => $regularPrice,
       'price'          => $price,
       'salePrice'      => $salePrice,
       'category'       => $product_cat->name,
       'variationPrice' => $variationPrice,
    ]);
    
    endwhile; 
    wp_reset_postdata();
    endif;
    
    return $productsResults;
}

2) Using a WC_Product_Query instead like:

function wtProductResults($data){
    global $woocommerce;
    
    $products = wc_get_products( array(
        'status'    => 'publish',
        'limit'     => -1,
        'category'  => array($data['cat']),
    ) );
    
    $productsResults = [];
    $currency        = get_woocommerce_currency_symbol();
   
    if ( sizeof($products) > 0 ) :
    foreach ( $products as $product ) :
    
    $term_name = get_term( $data['cat'], 'product_cat' )->name;
    
    if( $product->is_type('variable') ) {
        // Min variation price
        $regularPriceMin = $product->get_variation_regular_price(); // Min regular price
        $salePriceMin    = $product->get_variation_sale_price(); // Min sale price
        $priceMin        = $product->get_variation_price(); // Min price
    
        // Max variation price
        $regularPriceMax = $product->get_variation_regular_price('max'); // Max regular price
        $salePriceMax    = $product->get_variation_sale_price('max'); // Max sale price
        $priceMax        = $product->get_variation_price('max'); // Max price
    
        // Multi dimensional array of all variations prices 
        $variationsPrices = $product->get_variation_prices(); 
        
        $regularPrice = $salePrice = $price = '';
        $variationPrice = [
            'min' => $product->get_variation_price(),
            'max' => $product->get_variation_price('max')
        ];
    } 
    // Other product types
    else {
        $regularPrice   = $product->get_regular_price();
        $salePrice      = $product->get_sale_price();
        $price          = $product->get_price(); 
        $variationPrice = ['min' => '', 'max' => ''];
    }
    
    array_push( $productsResults , [
       'title'          => $product->get_name(),
       'productId'      => $product->get_id(),
       'permalink'      => $product->get_permalink(),
       'thumbnail'      => $product->get_image(),
       'excerpt'        => $product->get_short_description(),
       'regularPrice'   => $regularPrice,
       'price'          => $price,
       'salePrice'      => $salePrice,
       'category'       => $term_name,
       'variationPrice' => $variationPrice,
    ]);
    
    endforeach; 
    endif;
    
    return $productsResults;
}

Upvotes: 14

Abdullah Tahan
Abdullah Tahan

Reputation: 2129

add_filter( 'woocommerce_variable_price_html', 'bbloomer_variation_price_format_min', 9999, 2 );

function bbloomer_variation_price_format_min( $price, $product ) {
   $prices = $product->get_variation_prices('min', true );
   $maxprices = $product->get_variation_price( 'max', true ) ;
   $min_price = current( $prices['price'] );
   //$max_price = current( $maxprices['price'] );
   $minPrice = sprintf( __( 'from: %1$s', 'woocommerce' ), wc_price( $min_price ) );
   $maxPrice = sprintf( __( 'to: %1$s', 'woocommerce' ), wc_price( $maxprices ) );
   return $minPrice .' ' .$maxPrice ;
}

Upvotes: 0

Taghi Khavari
Taghi Khavari

Reputation: 6582

The Answer that @LoicTheAztec gave was very good and I liked the way he write the code but in my case I found on simple change that worked perfectly the way I want it to be both normal product price if it's normal product and variable product price if variable product This is the change I made and I used both wc_get_product(get_the_id()) and get_price_html()

        $product = wc_get_product( get_the_id() );
        array_push($productsResults , [
                'title'     => get_the_title(),
                'productId' => get_the_id(),
                'permalink' => get_the_permalink(),
                'thumbnail' => get_the_post_thumbnail(),
                'excerpt'   => get_the_excerpt(),
                'category'  => get_the_terms(get_the_id(),'product_cat'),
                'price'     => $product->get_price_html(),
        ]); 

this code should be inside while loop that I used with WP_Query()

Upvotes: 1

Related Questions