Create Programmatically a Woocommerce Product Variation With New Attribute Values

Create programmatically a WooCommerce product variation with new attribute values

Update January 2020: Changed to WC_Product method get_name() instead of get_title()

Update September 2018: Handling taxonomy creation (Thanks to Carl F. Corneil)

From a defined variable product ID You will find below, a custom function that will add (create) a Product variation. The variable parent product needs to have set for it the needed attributes.

You will need to provide some information as:

  • the array of attributes/values
  • the Sku, prices and stock….

This data has to be stored in a formatted multi dimensional array (see an example at the end).

This function will check if the attributes values (term name) already exist and if not:

  • it create it for the product attribute
  • set it in the parent variable product.

The custom function code:

/**
* Create a product variation for a defined variable product ID.
*
* @since 3.0.0
* @param int $product_id | Post ID of the product parent variable product.
* @param array $variation_data | The data to insert in the product.
*/

function create_product_variation( $product_id, $variation_data ){
// Get the Variable product object (parent)
$product = wc_get_product($product_id);

$variation_post = array(
'post_title' => $product->get_name(),
'post_name' => 'product-'.$product_id.'-variation',
'post_status' => 'publish',
'post_parent' => $product_id,
'post_type' => 'product_variation',
'guid' => $product->get_permalink()
);

// Creating the product variation
$variation_id = wp_insert_post( $variation_post );

// Get an instance of the WC_Product_Variation object
$variation = new WC_Product_Variation( $variation_id );

// Iterating through the variations attributes
foreach ($variation_data['attributes'] as $attribute => $term_name )
{
$taxonomy = 'pa_'.$attribute; // The attribute taxonomy

// If taxonomy doesn't exists we create it (Thanks to Carl F. Corneil)
if( ! taxonomy_exists( $taxonomy ) ){
register_taxonomy(
$taxonomy,
'product_variation',
array(
'hierarchical' => false,
'label' => ucfirst( $attribute ),
'query_var' => true,
'rewrite' => array( 'slug' => sanitize_title($attribute) ), // The base slug
),
);
}

// Check if the Term name exist and if not we create it.
if( ! term_exists( $term_name, $taxonomy ) )
wp_insert_term( $term_name, $taxonomy ); // Create the term

$term_slug = get_term_by('name', $term_name, $taxonomy )->slug; // Get the term slug

// Get the post Terms names from the parent variable product.
$post_term_names = wp_get_post_terms( $product_id, $taxonomy, array('fields' => 'names') );

// Check if the post term exist and if not we set it in the parent variable product.
if( ! in_array( $term_name, $post_term_names ) )
wp_set_post_terms( $product_id, $term_name, $taxonomy, true );

// Set/save the attribute data in the product variation
update_post_meta( $variation_id, 'attribute_'.$taxonomy, $term_slug );
}

## Set/save all other data

// SKU
if( ! empty( $variation_data['sku'] ) )
$variation->set_sku( $variation_data['sku'] );

// Prices
if( empty( $variation_data['sale_price'] ) ){
$variation->set_price( $variation_data['regular_price'] );
} else {
$variation->set_price( $variation_data['sale_price'] );
$variation->set_sale_price( $variation_data['sale_price'] );
}
$variation->set_regular_price( $variation_data['regular_price'] );

// Stock
if( ! empty($variation_data['stock_qty']) ){
$variation->set_stock_quantity( $variation_data['stock_qty'] );
$variation->set_manage_stock(true);
$variation->set_stock_status('');
} else {
$variation->set_manage_stock(false);
}

$variation->set_weight(''); // weight (reseting)

$variation->save(); // Save the data
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

Usage (example with 2 attributes):

$parent_id = 746; // Or get the variable product id dynamically

// The variation data
$variation_data = array(
'attributes' => array(
'size' => 'M',
'color' => 'Green',
),
'sku' => '',
'regular_price' => '22.00',
'sale_price' => '',
'stock_qty' => 10,
);

// The function to be run
create_product_variation( $parent_id, $variation_data );

Tested and works.

Part 2: Create programmatically a variable product and two new attributes in WooCommerce

You will get this in backend:

Sample Image

And it will work perfectly in front end.

Related: Create programmatically a product using CRUD methods in Woocommerce 3

Create programmatically a variable product and two new attributes in WooCommerce

After: Create programmatically a WooCommerce product variation with new attribute values

Here you get the way to create a new variable product with new product attributes + values:

/**
* Save a new product attribute from his name (slug).
*
* @since 3.0.0
* @param string $name | The product attribute name (slug).
* @param string $label | The product attribute label (name).
*/
function save_product_attribute_from_name( $name, $label='', $set=true ){
if( ! function_exists ('get_attribute_id_from_name') ) return;

global $wpdb;

$label = $label == '' ? ucfirst($name) : $label;
$attribute_id = get_attribute_id_from_name( $name );

if( empty($attribute_id) ){
$attribute_id = NULL;
} else {
$set = false;
}
$args = array(
'attribute_id' => $attribute_id,
'attribute_name' => $name,
'attribute_label' => $label,
'attribute_type' => 'select',
'attribute_orderby' => 'menu_order',
'attribute_public' => 0,
);


if( empty($attribute_id) ) {
$wpdb->insert( "{$wpdb->prefix}woocommerce_attribute_taxonomies", $args );
set_transient( 'wc_attribute_taxonomies', false );
}

if( $set ){
$attributes = wc_get_attribute_taxonomies();
$args['attribute_id'] = get_attribute_id_from_name( $name );
$attributes[] = (object) $args;
//print_r($attributes);
set_transient( 'wc_attribute_taxonomies', $attributes );
} else {
return;
}
}

/**
* Get the product attribute ID from the name.
*
* @since 3.0.0
* @param string $name | The name (slug).
*/
function get_attribute_id_from_name( $name ){
global $wpdb;
$attribute_id = $wpdb->get_col("SELECT attribute_id
FROM {$wpdb->prefix}woocommerce_attribute_taxonomies
WHERE attribute_name LIKE '$name'");
return reset($attribute_id);
}

/**
* Create a new variable product (with new attributes if they are).
* (Needed functions:
*
* @since 3.0.0
* @param array $data | The data to insert in the product.
*/

function create_product_variation( $data ){
if( ! function_exists ('save_product_attribute_from_name') ) return;

$postname = sanitize_title( $data['title'] );
$author = empty( $data['author'] ) ? '1' : $data['author'];

$post_data = array(
'post_author' => $author,
'post_name' => $postname,
'post_title' => $data['title'],
'post_content' => $data['content'],
'post_excerpt' => $data['excerpt'],
'post_status' => 'publish',
'ping_status' => 'closed',
'post_type' => 'product',
'guid' => home_url( '/product/'.$postname.'/' ),
);

// Creating the product (post data)
$product_id = wp_insert_post( $post_data );

// Get an instance of the WC_Product_Variable object and save it
$product = new WC_Product_Variable( $product_id );
$product->save();

## ---------------------- Other optional data ---------------------- ##
## (see WC_Product and WC_Product_Variable setters methods)

// THE PRICES (No prices yet as we need to create product variations)

// IMAGES GALLERY
if( ! empty( $data['gallery_ids'] ) && count( $data['gallery_ids'] ) > 0 )
$product->set_gallery_image_ids( $data['gallery_ids'] );

// SKU
if( ! empty( $data['sku'] ) )
$product->set_sku( $data['sku'] );

// STOCK (stock will be managed in variations)
$product->set_stock_quantity( $data['stock'] ); // Set a minimal stock quantity
$product->set_manage_stock(true);
$product->set_stock_status('');

// Tax class
if( empty( $data['tax_class'] ) )
$product->set_tax_class( $data['tax_class'] );

// WEIGHT
if( ! empty($data['weight']) )
$product->set_weight(''); // weight (reseting)
else
$product->set_weight($data['weight']);

$product->validate_props(); // Check validation

## ---------------------- VARIATION ATTRIBUTES ---------------------- ##

$product_attributes = array();

foreach( $data['attributes'] as $key => $terms ){
$taxonomy = wc_attribute_taxonomy_name($key); // The taxonomy slug
$attr_label = ucfirst($key); // attribute label name
$attr_name = ( wc_sanitize_taxonomy_name($key)); // attribute slug

// NEW Attributes: Register and save them
if( ! taxonomy_exists( $taxonomy ) )
save_product_attribute_from_name( $attr_name, $attr_label );

$product_attributes[$taxonomy] = array (
'name' => $taxonomy,
'value' => '',
'position' => '',
'is_visible' => 0,
'is_variation' => 1,
'is_taxonomy' => 1
);

foreach( $terms as $value ){
$term_name = ucfirst($value);
$term_slug = sanitize_title($value);

// Check if the Term name exist and if not we create it.
if( ! term_exists( $value, $taxonomy ) )
wp_insert_term( $term_name, $taxonomy, array('slug' => $term_slug ) ); // Create the term

// Set attribute values
wp_set_post_terms( $product_id, $term_name, $taxonomy, true );
}
}
update_post_meta( $product_id, '_product_attributes', $product_attributes );
$product->save(); // Save the data
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.


USAGE (example with 2 new attributes + values):

create_product_variation( array(
'author' => '', // optional
'title' => 'Woo special one',
'content' => '<p>This is the product content <br>A very nice product, soft and clear…<p>',
'excerpt' => 'The product short description…',
'regular_price' => '16', // product regular price
'sale_price' => '', // product sale price (optional)
'stock' => '10', // Set a minimal stock quantity
'image_id' => '', // optional
'gallery_ids' => array(), // optional
'sku' => '', // optional
'tax_class' => '', // optional
'weight' => '', // optional
// For NEW attributes/values use NAMES (not slugs)
'attributes' => array(
'Attribute 1' => array( 'Value 1', 'Value 2' ),
'Attribute 2' => array( 'Value 1', 'Value 2', 'Value 3' ),
),
) );

Tested and works.


Related:

  • Create new product attribute programmatically in Woocommerce
  • Create programmatically a WooCommerce product variation with new attribute values
  • Create programmatically a product using CRUD methods in Woocommerce 3

Create multiple product variations issue for a WooCommerce variable product

In your code, the first foreach loop need to be just before the following line of code:

$variation_id = wp_insert_post( $variation_post );

like:

function create_product_variations( $product_id, $variations_data ){
$product = wc_get_product($product_id);

$variation_post = array(
'post_title' => $product->get_name(),
'post_name' => 'product-'.$product_id.'-variation',
'post_status' => 'publish',
'post_parent' => $product_id,
'post_type' => 'product_variation',
'guid' => $product->get_permalink()
);

foreach( $variations_data as $variation_data ){

$variation_id = wp_insert_post( $variation_post );

$variation = new WC_Product_Variation( $variation_id );

foreach($_variation_data['attributes'] as $attribute => $term_name){
$taxonomy = 'pa_'.$attribute;

if( ! taxonomy_exists( $taxonomy ) ){
register_taxonomy(
$taxonomy,
'product_variation',
array(
'hierarchical' => false,
'label' => ucfirst($attribute),
'query_var' => true,
'rewrite' => array( 'slug' => sanitize_title($attribute)),
)
);
}

if( ! term_exists( $term_name, $taxonomy ) )
wp_insert_term( $term_name, $taxonomy );

$term_slug = get_term_by('name', $term_name, $taxonomy )->slug;

$post_term_names = wp_get_post_terms( $product_id, $taxonomy, array('fields' => 'names') );

if( ! in_array( $term_name, $post_term_names ) )
wp_set_post_terms( $product_id, $term_name, $taxonomy, true );

update_post_meta( $variation_id, 'attribute_'.$taxonomy, $term_slug );
}
$variation->save();
}
}

As wp_insert_post() create a product variation in database, with a unique variation ID, so it need to be done for each variation in your data array.

This should solve your main related problem.


Related:

  • Create programmatically a WooCommerce product variation with new attribute values
  • Create programmatically a variable product and two new attributes in WooCommerce


Related Topics



Leave a reply



Submit