I had a task to create a PHP script to import simple and variable products from JSON file using the WooCommerce REST API. Thought it might be worth sharing with others because I couldn’t find much information about products import from JSON using the API.
To make it easier to understand, I created a simple JSON file with one simple product and one variable product that have two product variations. You can get all files from Github repository.
products.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
[ { "product_id": 100, "type": "simple", "name": "My product 1", "description": "My product description 1", "regular_price": 100, "manage_stock": 1, "stock": 3, "weight": 0, "has_variations": 0 }, { "product_id": 200, "type": "variable", "name": "My product 2", "description": "My product description 2", "regular_price": 0, "manage_stock": 0, "stock": 0, "weight": 0, "attribute_name": "Color", "has_variations": 1 }, { "type": "product_variation", "parent_product_id": 200, "description": "My product variation 1", "regular_price": 120, "manage_stock": 1, "stock": 5, "weight": 0, "attribute_name": "Color", "attribute_value": "red" }, { "type": "product_variation", "parent_product_id": 200, "description": "My product variation description 2", "regular_price": 180, "manage_stock": 1, "stock": 6, "weight": 0, "attribute_name": "Color", "attribute_value": "green" } ] |
Getting started
What you need to do is download a PHP wrapper for the WooCommerce REST API. You can download it using composer from https://packagist.org/packages/automattic/woocommerce If you don’t have composer yet, then you can download it from https://getcomposer.org
Setup
Setup for the new WP REST API integration (WooCommerce 2.6 or later):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
require __DIR__ . '/vendor/autoload.php'; use Automattic\WooCommerce\Client; $woocommerce = new Client( 'http://example.com', 'ck_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 'cs_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', [ 'wp_api' => true, 'version' => 'wc/v2', ] ); |
1. Parse JSON
Convert JSON string to PHP array.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** * Parse JSON file. * * @param string $file * @return array */ function parse_json( $file ) { $json = json_decode( file_get_contents( $file ), true ); if ( is_array( $json ) && !empty( $json ) ) : return $json; else : die( 'An error occurred while parsing ' . $file . ' file.' ); endif; } |
2. Get all product attributes from JSON
We need to get all product attributes names and values from JSON file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/** * Get attributes and terms from JSON. * Used to import product attributes. * * @param array $json * @return array */ function get_attributes_from_json( $json ) { $product_attributes = array(); foreach( $json as $key => $pre_product ) : if ( !empty( $pre_product['attribute_name'] ) && !empty( $pre_product['attribute_value'] ) ) : $product_attributes[$pre_product['attribute_name']]['terms'][] = $pre_product['attribute_value']; endif; endforeach; return $product_attributes; } |
3. Get products and variations from JSON for importing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
/** * Get products from JSON and make them ready to import according WooCommerce API properties. * * @param array $json * @param array $added_attributes * @return array */ function get_products_and_variations_from_json( $json, $added_attributes ) { $product = array(); $product_variations = array(); foreach ( $json as $key => $pre_product ) : if ( $pre_product['type'] == 'simple' ) : $product[$key]['_product_id'] = (string) $pre_product['product_id']; $product[$key]['name'] = (string) $pre_product['name']; $product[$key]['description'] = (string) $pre_product['description']; $product[$key]['regular_price'] = (string) $pre_product['regular_price']; // Stock $product[$key]['manage_stock'] = (bool) $pre_product['manage_stock']; if ( $pre_product['stock'] > 0 ) : $product[$key]['in_stock'] = (bool) true; $product[$key]['stock_quantity'] = (int) $pre_product['stock']; else : $product[$key]['in_stock'] = (bool) false; $product[$key]['stock_quantity'] = (int) 0; endif; elseif ( $pre_product['type'] == 'variable' ) : $product[$key]['_product_id'] = (string) $pre_product['product_id']; $product[$key]['type'] = 'variable'; $product[$key]['name'] = (string) $pre_product['name']; $product[$key]['description'] = (string) $pre_product['description']; $product[$key]['regular_price'] = (string) $pre_product['regular_price']; // Stock $product[$key]['manage_stock'] = (bool) $pre_product['manage_stock']; if ( $pre_product['stock'] > 0 ) : $product[$key]['in_stock'] = (bool) true; $product[$key]['stock_quantity'] = (int) $pre_product['stock']; else : $product[$key]['in_stock'] = (bool) false; $product[$key]['stock_quantity'] = (int) 0; endif; $attribute_name = $pre_product['attribute_name']; $product[$key]['attributes'][] = array( 'id' => (int) $added_attributes[$attribute_name]['id'], 'name' => (string) $attribute_name, 'position' => (int) 0, 'visible' => true, 'variation' => true, 'options' => $added_attributes[$attribute_name]['terms'] ); elseif ( $pre_product['type'] == 'product_variation' ) : $product_variations[$key]['_parent_product_id'] = (string) $pre_product['parent_product_id']; $product_variations[$key]['description'] = (string) $pre_product['description']; $product_variations[$key]['regular_price'] = (string) $pre_product['regular_price']; // Stock $product_variations[$key]['manage_stock'] = (bool) $pre_product['manage_stock']; if ( $pre_product['stock'] > 0 ) : $product_variations[$key]['in_stock'] = (bool) true; $product_variations[$key]['stock_quantity'] = (int) $pre_product['stock']; else : $product_variations[$key]['in_stock'] = (bool) false; $product_variations[$key]['stock_quantity'] = (int) 0; endif; $attribute_name = $pre_product['attribute_name']; $attribute_value = $pre_product['attribute_value']; $product_variations[$key]['attributes'][] = array( 'id' => (int) $added_attributes[$attribute_name]['id'], 'name' => (string) $attribute_name, 'option' => (string) $attribute_value ); endif; endforeach; $data['products'] = $product; $data['product_variations'] = $product_variations; return $data; } |
4. Merge products and product variations
Used to loop through products, then loop through product variations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/** * Merge products and variations together. * Used to loop through products, then loop through product variations. * * @param array $product_data * @param array $product_variations_data * @return array */ function merge_products_and_variations( $product_data = array(), $product_variations_data = array() ) { foreach ( $product_data as $k => $product ) : foreach ( $product_variations_data as $k2 => $product_variation ) : if ( $product_variation['_parent_product_id'] == $product['_product_id'] ) : // Unset merge key. Don't need it anymore unset($product_variation['_parent_product_id']); $product_data[$k]['variations'][] = $product_variation; endif; endforeach; // Unset merge key. Don't need it anymore unset($product_data[$k]['_product_id']); endforeach; return $product_data; } |
5. A simple function to print status message
1 2 3 4 5 6 7 8 9 |
/** * Print status message. * * @param string $message * @return string */ function status_message( $message ) { echo $message . "\r\n"; } |
Import products to WooCommerce using the API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
try { $json = parse_json( 'products.json' ); // Import Attributes foreach ( get_attributes_from_json( $json ) as $product_attribute_name => $product_attribute ) : $attribute_data = array( 'name' => $product_attribute_name, 'slug' => 'pa_' . strtolower( $product_attribute_name ), 'type' => 'select', 'order_by' => 'menu_order', 'has_archives' => true ); $wc_attribute = $woocommerce->post( 'products/attributes', $attribute_data ); if ( $wc_attribute ) : status_message( 'Attribute added. ID: '. $wc_attribute['id'] ); // store attribute ID so that we can use it later for creating products and variations $added_attributes[$product_attribute_name]['id'] = $wc_attribute['id']; // Import: Attribute terms foreach ( $product_attribute['terms'] as $term ) : $attribute_term_data = array( 'name' => $term ); $wc_attribute_term = $woocommerce->post( 'products/attributes/'. $wc_attribute['id'] .'/terms', $attribute_term_data ); if ( $wc_attribute_term ) : status_message( 'Attribute term added. ID: '. $wc_attribute['id'] ); // store attribute terms so that we can use it later for creating products $added_attributes[$product_attribute_name]['terms'][] = $term; endif; endforeach; endif; endforeach; $data = get_products_and_variations_from_json( $json, $added_attributes ); // Merge products and product variations so that we can loop through products, then its variations $product_data = merge_products_and_variations( $data['products'], $data['product_variations'] ); // Import: Products foreach ( $product_data as $k => $product ) : if ( isset( $product['variations'] ) ) : $_product_variations = $product['variations']; // temporary store variations array // Unset and make the $product data correct for importing the product. unset($product['variations']); endif; $wc_product = $woocommerce->post( 'products', $product ); if ( $wc_product ) : status_message( 'Product added. ID: '. $wc_product['id'] ); endif; if ( isset( $_product_variations ) ) : // Import: Product variations // Loop through our temporary stored product variations array and add them foreach ( $_product_variations as $variation ) : $wc_variation = $woocommerce->post( 'products/'. $wc_product['id'] .'/variations', $variation ); if ( $wc_variation ) : status_message( 'Product variation added. ID: '. $wc_variation['id'] . ' for product ID: ' . $wc_product['id'] ); endif; endforeach; // Don't need it anymore unset($_product_variations); endif; endforeach; } catch ( HttpClientException $e ) { echo $e->getMessage(); // Error message } |
You can find the script on Github repository