8

I'm using the WooCommerce REST API to e.g. get all products with variations, but I encounter a fairly large problem regarding the number of fired requests. I need help optimizing the situation below.

Situation: A webshop with 50 products and 5 variations for each product.

  1. Get all master products (~1 request)
  2. Get all variations for each product (50 requests)

Total count of request = 51

How can I do this without firing of 51 requests? Is't possible to get all products with their variations eager loaded somehow?

Christian Gerdes
  • 279
  • 1
  • 2
  • 16
  • It depends on your use case. When do you *need* to query the data? If you only showcase the 'base' product, then allow the user to pick a variation later, then you only need to make a single secondary call once the variation is selected. – Obsidian Age Mar 18 '18 at 20:49
  • I only fetch all products with variations once. Since many of our clients have more than 100k product without variations it often result in more than 1mio requests which is way to much and not very scalable – Christian Gerdes Mar 18 '18 at 20:54
  • I need to query the data once. How would I do that, @ObsidianAge ? – Christian Gerdes Mar 18 '18 at 21:47
  • I am afraid this is not possilble with the latest version of the official REST API. But is should be possible using GraphQL APIs => https://github.com/wp-graphql/wp-graphql-woocommerce – coccoinomane Dec 07 '20 at 06:47
  • @christian gerdes, could you solve it? – Martin Larizzate Dec 09 '20 at 12:11

3 Answers3

11

Yes, you can do it by customizing the WooCommerce Product REST API Response.

Here I have attached some code that will help you.

add_filter('woocommerce_rest_prepare_product_object', 'custom_change_product_response', 20, 3);
add_filter('woocommerce_rest_prepare_product_variation_object', 'custom_change_product_response', 20, 3);

function custom_change_product_response($response, $object, $request) {
    $variations = $response->data['variations'];
    $variations_res = array();
    $variations_array = array();
    if (!empty($variations) && is_array($variations)) {
        foreach ($variations as $variation) {
            $variation_id = $variation;
            $variation = new WC_Product_Variation($variation_id);
            $variations_res['id'] = $variation_id;
            $variations_res['on_sale'] = $variation->is_on_sale();
            $variations_res['regular_price'] = (float)$variation->get_regular_price();
            $variations_res['sale_price'] = (float)$variation->get_sale_price();
            $variations_res['sku'] = $variation->get_sku();
            $variations_res['quantity'] = $variation->get_stock_quantity();
            if ($variations_res['quantity'] == null) {
                $variations_res['quantity'] = '';
            }
            $variations_res['stock'] = $variation->get_stock_quantity();

            $attributes = array();
            // variation attributes
            foreach ( $variation->get_variation_attributes() as $attribute_name => $attribute ) {
                // taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`
                $attributes[] = array(
                    'name'   => wc_attribute_label( str_replace( 'attribute_', '', $attribute_name ), $variation ),
                    'slug'   => str_replace( 'attribute_', '', wc_attribute_taxonomy_slug( $attribute_name ) ),
                    'option' => $attribute,
                );
            }

            $variations_res['attributes'] = $attributes;
            $variations_array[] = $variations_res;
        }
    }
    $response->data['product_variations'] = $variations_array;

    return $response;
}

I have done by this way. I have got all variations in the single parameter product_variations.

XciD
  • 2,537
  • 14
  • 40
Ajay Ghaghretiya
  • 784
  • 1
  • 6
  • 30
  • Yeah, that make sense. Thank you since we're also developing a wp-plugin, but is it possible without altering code on the shop-end? The code should be used access shops/customers and not in a plugin for now. Is that possible? – Christian Gerdes Mar 20 '18 at 18:27
  • No, you can not get the all variations without the customize the WooCommerce REST API. and it is just a filter, WooCommerce Provide this types of filters for the customize the response as you need. you can put this code in theme's functions.php file. – Ajay Ghaghretiya Mar 21 '18 at 04:43
  • For me the line after the if clause is closed has to be `$response->data['product_variations'] = $variations_array;` – SunnyRed Apr 14 '18 at 18:51
  • Thanks to all for the solutions here. I have one question about the 'option' field. How do you generate the array of options? I've tried get_terms , get_options().. – user3200548 Aug 27 '21 at 18:12
  • This is brilliant! you just saved my day. Thank you man. – awran5 May 26 '22 at 06:16
  • Great contribution! I ended up instantiating the controller that handles the variations so I could get a response exactly like the variations API call. It's not the cleanest way probably but it works well: `$variation = new WC_Product_Variation($variation_id); $controller = new WC_REST_Product_Variations_Controller(); $varReq = $controller->prepare_object_for_response($variation, $request); $variations_array[] = $varReq->data;` – lbarbosa Jun 09 '22 at 11:20
4

Unfortunately this is not possible with their "new" API without having access to the server. So third party companies developing tools for their customers who run WooCommerce are screwed.

The problem of having to make a request per variation is not the only issue. Counting products is also impossible. We now have to load the data of all products just to count them...

If a customer has 10,000 products in their store and 3 variations for each we have to make 30K+ individual requests... (instead of a couple dozen, one per page).

Personally since this is totally impractical, and is most likely to get us blacklisted by some firewall, I decided to use the old API: https://woocommerce.github.io/woocommerce-rest-api-docs/v3.html#view-products-count

Instead of the "new" one: https://woocommerce.github.io/woocommerce-rest-api-docs/

When will the old API be completely removed from WooCommerce? I have no idea but there is no other realistic option anyway.

FlorianB
  • 2,188
  • 18
  • 30
  • 1
    Agreed. The decision the remove the ability to fetch a products variations in a single request decreases the value of the API substantially – Christian Gerdes Oct 31 '20 at 07:22
-2

You can get product variations all in 1 request making

GET /products/<product-id>/variations/

then iterate over the results to find the matching one and retrieve the id

Esteban Panelli
  • 178
  • 2
  • 10