Hey there, long time, no see once again! Things are very busy between work and raising a baby. Today we are going to talk about a subject that is pretty much hard to find a reliable source as a base:
Importing WooCommerce Products by Code! Ideal for when you want to bulk-import products on a new (or old) e-commerce website.
Intro
Adding a product on WooCommerce is a fast but boring process, especially if you have to import 100s or even 1000s of products. If by any chance you have an easy way to access all info on a CSV (from your ERP) or are in a database, then you can speed up the process, from taking weeks to taking a couple of days!
This is going to be a little bit big of a post, but it is worth your time if you need knowledge like this.
Not covered in this post
- Adding Variable/Virtual/Whatever products, we will only add simple products. Variable products will be covered in the future
- Creating categories (we will only get the ID from the slug - or the pretty URL)
- Adding attributes to the database or the product
Requirements
You need at least the following details for each product:
- Title
- Price
- Description
- SKU
- An image (a URL accessible online is by far the fastest method, as long as the remote host allows you to directly download the image)
- A category ID (I will cover how to get the WooCommerce Category ID by the category slug in the post, but not how to create them)
You can also add product attributes to be visible in the "Additional Information" tab below a product, but this will not be covered here, as stated in the "Not covered in this post" section.
Adding a simple product
<?php
$product = new WC_Product_Simple(); // We initialize a simple WooCommerce product
$product->set_name("Super awesome product"); // This is our product title!
$product->set_sku("SAP-001"); // This is the Stock-Keeping Unit code.
$product->set_regular_price("19.99"); // WooCommerce will use the default currency of your store.
$product->set_slug("super-awesome-product"); // Will be used by WordPress as the pretty url, in this case the product's URL will be: www.example.com/product/super-awesome-product
$product->set_description("<p>This is the full product description.</p> <p>WordPress will filter some HTML code out, so be sure to double-check it.</p>");
// You can also set a short description, using the following code:
$product->set_short_description("This is a short description for the Super Awesome Product");
// See the "Downloading an image and getting the ID" section for a basic overview.
$image_id = download_image("https://example.com/static/super-image.jpg", "super-awesome-product")
$product->set_image_id($image_id);
// See the "Get a Term ID by the category slug" section for a basic overview.
$term_id = find_term_id('awesome-category')
$product->set_category_ids(array($term_id)); // We will get the Term ID in a later section
$product->save(); // Save the Simple Product to the DB
?>
Downloading an image, and getting the ID
<?php
function download_image($url, $slug) {
$imagetype = end(explode('/', getimagesize($imageurl)['mime']));
$uniq_name = date('dmY') . '' . (int) microtime(true);
$slug = $slug . '-' . substr(time(), -5);
$filename = $slug . '.' . $imagetype;
$uploaddir = wp_upload_dir();
$uploadfile = $uploaddir['path'] . '/' . $filename;
$contents = file_get_contents($imageurl);
$savefile = fopen($uploadfile, 'w');
fwrite($savefile, $contents);
fclose($savefile);
$wp_filetype = wp_check_filetype(basename($filename), null);
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => $filename,
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment($attachment, $uploadfile);
$imagenew = get_post($attach_id);
$fullsizepath = get_attached_file($imagenew->ID);
$attach_data = wp_generate_attachment_metadata($attach_id, $fullsizepath);
wp_update_attachment_metadata($attach_id, $attach_data);
return $attach_id;
}
?>
I will not fully explain this code, but in a nutshell:
- We provide download_image with a URL (the image we want to set as the default one for the product) and a slug (this could be the same as the product's slug, it's good for Image SEO from what I hear)
- We get the image using file_get_contents and save it to the WordPress upload folder.
- We import the image as an attachment and get the Attachment ID that we use as a return on our function.
Get a Term ID by the category slug.
Getting the term's info
<?php
function find_term_id($cat_slug) {
$termdetails = get_term_by('slug', $cat_slug, 'product_cat');
return $termdetails->->term_id;
}
?>
get_term_by accepts 3 parameters, you can have an in-depth look at the official WordPress Developer Resources page for "get_term_by".
get_term_by returns an object that holds the following information:
- term_id (that's what we want)
- name
- slug
- term_group
- term_taxonomy_id
- taxonomy
- description
- parent
- count
- filter
Getting the term's ID
To get the term ID, we want to call $termdetails->term_id (it's an object, not an array, so $termdetails['term_id'] will result in an error)
How to use it for bulk importing
Wrap the code in the 'Adding a simple product' inside a function, and replace all strings with variables. You can use an array for each product's details, and call it in a loop like this:
<?php
foreach ($products AS $product) {
import_product($product);
}
?>
For this to work though, you must include the WordPress wp-load.php file as well as the image.php include, like this:
<?php
include('wp-load.php');
include_once(ABSPATH . 'wp-admin/includes/image.php');
?>
The wp-load.php path should be relative to the location of the PHP file you're going to use.
How to make it better?
You should at least add error handling for downloading the images, saving the product and getting the term ID.
Chances are you do not have a pregenerated slug, so you could use the sanitize_title() function to generate one from the product title. See the WordPress Developer Resource page for "sanitize_title"
That's it for this blog post, if you found it useful you upvote and a comment will be more than welcome!
Is there something wrong with my snippets? Let me know!