skip to Main Content

I am relatively new to PHP, WordPress, and WooCommerce. But I have 5 years experience in Oracle (SQL and PL/SQL) and also did a lot of JavaScript and some TypeScript.

I am working for a client of mine. He has a WooCommerce-based webshop. I need to update stock_quantity, backorders, and stock_status for products and product variations according to data coming from another HTTP server. Currently, I have a working solution in TS/JS, which runs on a Linode server and is basically retrieving and combining/preparing data to update WooCommerce. But because it utilizes the WooCommerce HTTP API which has batch update limits (100 in a second, all variations have to be updated per parent id also 1 per second), and I am updating about 2500 products and product variations, it takes very long for the process to complete (~10 min).

The process in steps:

  1. Get stock from 3rd party API, this is a list of SKUs and their stock amount.
  2. Get all WC products and WC product variations
  3. Match stock list on WC product and product variation lists by SKU.
  4. Update products in batches of 100 per second (/products/batch)
  5. Update product variations per parent product per second (/products/${id}/variations/batch)

I think there is a better approach, I was thinking of:

  • PHP procedure, closer to DB, maybe no limit on batch updates? But I am unable to find any WooCommerce PHP API other than https://github.com/woocommerce/wc-api-php, which is a wrapper for the HTTP API, so in the end, would return the same result.
  • MySQL Database procedure, in DB, should run way quicker. Difficult to dissect what tables need to be updated exactly with what values. Is the MySQL DB able to do HTTP requests?

What approach would be best concerning performance, security, and keeping updates of PHP, WordPress, and WooCommerce in mind?

2

Answers


  1. Using the WC API to do this is by far the most "reliable" way to accomplish your goal. The API is very stable and doesn’t (usually) break when internals are changed. It is, however, the slowest method, as you’ve noticed.

    Your next best option is to run an update using the Woocommerce CRUD methods but, again, not super speedy but faster than using the API.

    $product = wc_get_product( $product_id );
    $product->set_stock = 100;
    $product->set_stock_status = 'instock';
    $product->save();
    

    Updating the DB directly is by far the fastest way but error prone because, for example, while stock status is in wp_postmeta, it’s ALSO a taxonomy and both have to match or you’ll have unintended consequences.

    Login or Signup to reply.
  2. Based on additional comments by @HotFix and answer provided by @VegasGeek, I created a PHP file that can be run on the WordPress server from the command line or a cron job.

    The idea:

    • We’ll create a PHP script that will load the WordPress inside, call the external API and update the product quantity if needed.

    Let’s assume that 3rd party external API returns a JSON response like this

    {
      "products": [
        {
          "id": 123,
          "sku": "PR1234",
          "name": "Product 1",
          "stock_quantity": 10
        },
        {
          "id": 456,
          "sku": "PR-3333",
          "name": "Product 2",
          "stock_quantity": 5
        }
      ]
    }
    
    

    There a 2 products with SKU and quantity info.

    The PHP script requires wp-load.php so replace my path with yours. For simplicity, I created this file in the website root so I can run it in the browser too but you can put it somewhere else and change the path. It’s only important that the path to wp-load.php is correct. This line of code will load the WordPress and all plugins and make it available to the script.

    I am simulating API response with a simple static JSON file, you replace the endpoint with the URL of the real API. Also, you may need to add some authentication to access the external API and your data will probably be different to my example, so you’ll have to change the code a bit. We are using curl to get the data from the API so it should be easy to modify the call.

    Then, we iterate over the products, find the product in WooCommerce by SKU, check if the quantity has changed and update if needed.

    
    // Load WordPress
    define( 'WP_USE_THEMES', false );
    //require_once( 'path/to/wp-load.php' );
    require_once "wp-load.php";
    // Set the API endpoint
    //$api_endpoint = 'https://your-api.com/products';
    $api_endpoint = 'http://bytwoo.local/TestData.json';
    
    echo "<pre>";
    
    // Build the cURL request to retrieve the list of products from the external API
    $ch = curl_init();
    curl_setopt( $ch, CURLOPT_URL, $api_endpoint );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    
    // Execute the API request and decode the response
    $response = json_decode( curl_exec( $ch ), true );
    curl_close( $ch );
    
    // Check if the API request was successful and if the products were found
    if ( isset( $response['products'] ) && is_array( $response['products'] ) ) {
        // The products were found, loop through the products
        foreach ( $response['products'] as $product ) {
            // Get the product SKU and stock quantity
            $product_sku    = $product['sku'];
            $stock_quantity = $product['stock_quantity'];
    
            // Get the product ID from the SKU
            $product_id = wc_get_product_id_by_sku($product_sku);
            // Get the WooCommerce product object
            $wc_product =  wc_get_product($product_id);
    
            // Check if the product exists in the WooCommerce shop
            if ( ! empty( $wc_product ) ) {
                // The product exists, get the current stock quantity
                $current_stock_quantity = $wc_product->get_stock_quantity();
    
                // Check if the stock quantity needs to be updated
                if ( $stock_quantity != $current_stock_quantity ) {
                    // Set the new stock quantity and stock status
                    $wc_product->set_stock_quantity($stock_quantity);
                    $wc_product->set_stock_status( 'instock' );
    
                    // Save the product
                    $wc_product->save();
    
                    echo PHP_EOL."Successfully updated stock quantity for product with SKU '$product_sku' to $stock_quantity";
                } else {
                    echo PHP_EOL."Stock quantity for product with SKU '$product_sku' is already up to date";
                }
            } else {
                echo PHP_EOL."Product with SKU '$product_sku' not found in WooCommerce shop";
            }
        }
    } else {
        echo PHP_EOL."No products found in external API";
    }
    
    echo "</pre>";
    

    I tested it with 2 products, only one of them needed an update. The result (log):

    Stock quantity for product with SKU 'PR1234' is already up to date
    Successfully updated stock quantity for product with SKU 'PR-3333' to 5
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search