3

It is possible to bulk create products on WooCommerce? I am using the wp-cli Product command but it seems that I have to create one by one.

<?php

$products = array(
    array('title' => 'My product 1'),
    array('title' => 'My product 2'),
    // ...
    // 10.000 more products
);

foreach ($products as $product) {
    $cliProduct = new WC_CLI_Product();
    $cliProduct->create(array(), $product);
    WP_CLI::success("Added Product #{$product['title']}");
}

This takes a lot of time since it is going to make a query for each product, even worse, it is going to be a cron job that will be run regularly. I also have to check if the product exist, in that case, update it instead of create a new product.

So the number of queries will be multiplied by 2.

Product Exists? Update it, else Create it

Is there a better way to do this? Maybe I should query the database directly, but it looks dirty.

Is there any WP function to query the database without having to create my own DB connection?

Carlos Goce
  • 1,625
  • 4
  • 22
  • 33
  • 1
    You want to create only by using `wp-cli`? or a custom function will do? If so then I can answer your question by building with my [this answer](http://stackoverflow.com/a/41223249/5019802). – Raunak Gupta Feb 06 '17 at 10:26
  • Yes. Any script that creates products will be valid. Even the WooCommerce REST API will be valid (trying that now). I will check your answer. – Carlos Goce Feb 06 '17 at 11:28

2 Answers2

6

A small note I had written this answer way back in 2017 at that time WooCommerce version was below < 3.0. So if you are using WooCommerce version 3.0. then please refer to this answer.

As of March 2022 this answer still works but I will recommend using this answer for > v3.0.

Assuming you have an array like this and you have Unique SKU to identify product.

$products = [
    0 => [
        'title' => 'My Simple product 1',
        'sku' => 'sku1',
        'product_cat' => 'My cat'
    //...
    //...
    ],
    1 => [
        'title' => 'My Simple product 1',
        'sku' => 'sku1'
    //...
    //...
    ]
];

Pass the above array through myCustomProduct() method.

function myCustomProduct($product_array)
{
    if (!empty($product_array)):
        foreach ($product_array as $product):
            $product_id = wc_get_product_id_by_sku($product['sku']);
            //no product exist with the given SKU so create one
            if (!$product_id):
                $post = [
                    'post_author' => '',
                    'post_content' => $product['content'],
                    'post_status' => "publish",
                    'post_title' => wp_strip_all_tags($product['title']),
                    'post_name' => $product['title'],
                    'post_parent' => '',
                    'post_type' => "product",
                ];
                //Create Post
                $product_id = wp_insert_post($post, $wp_error);

                //set Product Category
                wp_set_object_terms($product_id, $product['product_cat'], 'product_cat');

                //set product type
                wp_set_object_terms($product_id, 'simple', 'product_type');

                update_post_meta($product_id, '_sku', $product['sku']);
                update_post_meta($product_id, 'total_sales', '0');

            //product found
            else:
                $post = [
                    'ID' => $product_id,
                    'post_title' => $product['title'],
                    'post_content' => $product['content'],
                ];
                $post_id = wp_update_post($post, true);
//              if (is_wp_error($post_id))
//              {
//                  $errors = $post_id->get_error_messages();
//                  foreach ($errors as $error)
//                  {
//                      echo $error;
//                  }
//              }
            endif;

            update_post_meta($product_id, '_visibility', 'visible');
            update_post_meta($product_id, '_stock_status', 'instock');
            update_post_meta($product_id, '_product_attributes', array());
            update_post_meta($product_id, '_manage_stock', "yes");
            update_post_meta($product_id, '_backorders', "no");
            update_post_meta($product_id, '_stock', $product['qty']);
            update_post_meta($product_id, '_price', $product['price']);
            //update_post_meta($product_id, '_downloadable', 'yes');
            //update_post_meta($product_id, '_virtual', 'yes');
            //update_post_meta($product_id, '_regular_price', "1");
            //update_post_meta($product_id, '_sale_price', "1");
            //update_post_meta($product_id, '_purchase_note', "");
            //update_post_meta($product_id, '_featured', "no");
            //update_post_meta($product_id, '_weight', "");
            //update_post_meta($product_id, '_length', "");
            //update_post_meta($product_id, '_width', "");
            //update_post_meta($product_id, '_height', "");
            //update_post_meta($product_id, '_sale_price_dates_from', "");
            //update_post_meta($product_id, '_sale_price_dates_to', "");
            //update_post_meta($product_id, '_price', "1");
            //update_post_meta($product_id, '_sold_individually', "");
        endforeach;
    endif;
}

This'll give you a brief idea as how to create/update product; if you need any further assistance then you have to share your 4-5 array elements, so that I can get to know what type of product you want to create and what field/meta it will be having.

Hope this helps!

Raunak Gupta
  • 10,412
  • 3
  • 58
  • 97
  • Thank you for the help but this is going to be really slow. Too many queries. I already manage to create single products, the problem is how to create products in chunks, so you can import +5000 products fast without adding the products one by one. Otherwise it is going to take too much time. – Carlos Goce Feb 09 '17 at 09:52
  • It will be slow because WooCommerce does not store data in a single flat table, so as you want "**first check then update or create**" so it will take time; but if you can provide few sample data then I can optimized my code; it real tough to say what are the fields you want to save without see the array. – Raunak Gupta Feb 09 '17 at 10:13
  • 1
    Yes, but I found that WooCommerce had a "products/batch" endpoint that I was checking out. I checked the source code for that endpoint and it looks like it just iterates over all items and calls create_item on each, there is no optimization for creating them in batch. So I think that I would stick to your answer. – Carlos Goce Feb 09 '17 at 10:27
  • Ya that's true. – Raunak Gupta Feb 09 '17 at 10:34
  • 2
    What about for variable products? – David Apr 23 '20 at 06:52
  • Ok so I have tried this and what I did was just set the script to run once the plugin is activated and when it runs the first time all products are created without any issues perfectly, but then when I run the script again it just duplicated the products again even though the SKU value is identical, it looks like it is not recognizing the sku even though they already exist? – Blu3 Mar 15 '22 at 12:02
  • @Blu3: I have written this 4-5yr back at that time it was working, now need to check once, can u DM me your 2-3 sample data with your script so that I can check and update my answer. – Raunak Gupta Mar 19 '22 at 09:07
  • 1
    @RaunakGupta ok I have created a room and sent you the information you seek, looking forward to your reply. – Blu3 Mar 19 '22 at 15:54
1

For WooCommerce Version 3.0 or above.

Assuming you have an array like this and you have Unique SKU to identify product.

$products = [
    0 => [
        'title' => 'My Simple product 1',
        'sku' => 'sku1',
        'category_ids' => [23,45]
    //...
    //...
    ],
    1 => [
        'title' => 'My Simple product 1',
        'sku' => 'sku1'
    //...
    //...
    ]
];

Pass the above array through wh_myCustomProduct() method.

function wh_myCustomProduct($product_array)
{
    if (!empty($product_array)):
        foreach ($product_array as $product):
            $product_id = wc_get_product_id_by_sku($product['sku']);
            //no product exist with the given SKU so create one
            if (empty($product_id)):
                
                $product_id = wh_createOrUpdateProduct($product);
            //product found
            else:
                
                $product_id = wh_createOrUpdateProduct($product,$product_id);
            endif;

        endforeach;
    endif;
}

function wh_createOrUpdateProduct($product, $productId = 0){
    $objProduct = new WC_Product($productId);
    $objProduct->set_sku($product['id']); //Set product SKU.
    $objProduct->set_name($product['title']); //Set product name.
    $objProduct->set_description($product['description']); //Set product description.
    $objProduct->set_description($product['price']); //Set product price.


    $objProduct->set_category_ids($product['category_ids']); //Set product category ID.

    $objProduct->set_stock_status('instock');
    $objProduct->set_manage_stock(true); //Set true if you want WooCommerce to manage your stock
    $objProduct->set_stock_quantity($product['rating']['count']); //Set product stock qty.
    $objProduct->set_status('publish'); //Set product status

    $productID = $objProduct->save(); //Saving the data to create new product, it will return product ID.
    return $productID;
}

Hope this helps!

Reference:

  • This is the WooCommerce official doc
  • You can also refer to this article where I have explained in detail how to use Product CRUD

Related:

Raunak Gupta
  • 10,412
  • 3
  • 58
  • 97