How to set attribute as variation in Woocommerce - php

I have a front-end form I am creating to allow users to publish a variable product to my shop from the front end with predefined attributes and variations.
I have found this very helpful question: here Which shows me how to set the product type as variable and assign my predefined attributes in the attributes section of the product data.
However when I am on the backend of Wordpress/Woocommerce and editing the product I click on variations and none are set, I look at the attributes and my "resolution" attribute is set with my 3 items.
How do I make this to where it will actually set those attributes to variations of my form? Do I need to use wp_insert_post? Looking in phpmyadmin it just looks like product variations are assigned to a parent_id (product id) and post type is product_varition and so on.
$new_post = array(
'post_title' => esc_attr(strip_tags($_POST['postTitle'])),
'post_content' => esc_attr(strip_tags($_POST['postContent'])),
'post_status' => 'publish',
'post_type' => 'product',
'tags_input' => array($tags)
);
$skuu = rand();
$post_id = wp_insert_post($new_post);
update_post_meta($post_id, '_sku', $skuu );
//my array for setting the attributes
$avail_attributes = array(
'high-resolution',
'medium-resolution',
'low-resolution'
);
//Sets the attributes up to be used as variations but doesnt actually set them up as variations
wp_set_object_terms ($post_id, 'variable', 'product_type');
wp_set_object_terms( $post_id, $avail_attributes, 'pa_resolution' );
$thedata = array(
'pa_resolution'=> array(
'name'=>'pa_resolution',
'value'=>'',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'
)
);
update_post_meta( $post_id,'_product_attributes',$thedata);
update_post_meta( $post_id, '_visibility', 'search' );
update_post_meta( $post_id, '_stock_status', 'instock');
So just to be clear (I tend to be confusing) the above does create my variable product from the front end, and when I look at the product in the backend it is a variable product, it has the resolution attribute set and has my 3 terms (high-res, medium-res, low-res) as attributes. I just need to take this a step further where they are actually set as variations so people can place an order.

I got it working for my situation by using update_post_meta and wp_insert_post. Because I already setup my attributes and terms all I needed was a way to add to the above code so that when the product is created it not only will assign the attributes to the product but insert them as variations in the database.
Here is my solution:
//insert variations post_type
$i=1;
while ($i<=3) {
$my_post = array(
'post_title' => 'Variation #' . $i . ' of ' . esc_attr(strip_tags($_POST['postTitle'])),
'post_name' => 'product-' . $post_id . '-variation-' . $i,
'post_status' => 'publish',
'post_parent' => $post_id,
'post_type' => 'product_variation',
'guid' => home_url() . '/?product_variation=product-' . $post_id . '-variation-' . $i
);
// Insert the post into the database
wp_insert_post( $my_post );
$variable_id = $post_id + 1;
$variable_two = $variable_id + 1;
$variable_three = $variable_two + 1;
update_post_meta( $variable_id, 'attribute_pa_resolution', 'high-resolution');
update_post_meta( $variable_id, '_price', 8.50 );
update_post_meta( $variable_id, '_regular_price', '8.50');
update_post_meta( $variable_two, 'attribute_pa_resolution', 'medium-resolution');
update_post_meta( $variable_two, '_price', 5.50 );
update_post_meta( $variable_two, '_regular_price', '5.50');
update_post_meta( $variable_three, 'attribute_pa_resolution', 'low-resolution');
update_post_meta( $variable_three, '_price', 3.50 );
update_post_meta( $variable_three, '_regular_price', '3.50');
$i++;
}

I have been struggling for the last two days on implementing in my plugin the ability to set up product variation in Woocommerce.
I managed to get all correct data in DB but Woocommerce wasn't retrieving as I thought it would.
The problem were the 'transient' stored in wp_options table.
This is the code that had me up and running with WC 2.6.0:
CREATING VARIATION BASED UPON SELECTED ATTRIBUTES ($_POST['term_id_arr'] are a list of all attributes chosen from frontend for creating product. I'm sorry but I am not yet allowed to post images on stack.. Front-end form with variations created)
$opzioni_arr=$_POST['term_id_arr'];
$qta = count($opzioni_arr);
if ($qta>0){
$ID = $post_id;
//make product type be variable:
wp_set_object_terms ($ID,'variable','product_type');
foreach ($opzioni_arr as $opzioni_val){
$new_arr = explode("/",$opzioni_val);
$att_taxonomy = $new_arr[0];
$att_slug = $new_arr[1];
$att_id =$new_arr[2];
$att_arr[$att_taxonomy][$att_id]=$att_slug;
$att_due_arr[$att_taxonomy][$att_taxonomy.'*'.$att_id]=$att_slug;
}
//################### Add attributes to main product: ####################
foreach ($att_arr as $att_arr_key=>$att_arr_val){
//Array for setting attributes
unset ($avail_attributes);
foreach ($att_arr_val as $key_two=>$val_two){
$avail_attributes[] = $val_two;
}
wp_set_object_terms($ID, $avail_attributes, $att_arr_key);
$thedata [$att_arr_key]= Array(
'name'=>$att_arr_key,
'value'=>'',
'is_visible' => 1,
'is_variation' => 1,
'is_taxonomy' => 1,
'position' => '1'
);
}
update_post_meta( $ID,'_product_attributes',$thedata);
//########################## Done adding attributes to product #################
//function to create combinations from attributes
$combinations=lasap_get_combinations($att_due_arr);
foreach ($combinations as $key=>$val){
// Start creating variations
// The variation is simply a post
// with the main product set as its parent
// you might want to put that in a loop or something
// to create multiple variations with multiple values
$parent_id = $ID;
$variation = array(
'post_title' => 'Prodotto #' . $parent_id . ' Variante',
'post_content' => '',
'post_status' => 'publish',
'post_parent' => $parent_id,
'post_type' => 'product_variation'
);
// The variation id
$variation_id = wp_insert_post( $variation );
// Regular Price ( you can set other data like sku and sale price here )
update_post_meta($variation_id, '_sku', $sku);
update_post_meta($variation_id, '_regular_price', $regular_price);
update_post_meta($variation_id, '_sale_price', $sale_price);
update_post_meta($variation_id, '_sale_price_dates_from', $datasaldodal_time);
update_post_meta($variation_id, '_sale_price_dates_to', $datasaldoal_time);
if (($sale_price!='' AND ($sale_price<=$regular_price))){$price=$sale_price;} else {$price=$regular_price;}
update_post_meta($variation_id, '_price', $price);
update_post_meta($variation_id, '_thumbnail_id', $thumbnail_id);
update_post_meta($variation_id, '_manage_stock', $manage_stock);
update_post_meta($variation_id, '_stock_status', $stock_status);
update_post_meta($variation_id, '_stock', $stock);
update_post_meta($variation_id, '_stock_soglia', $stock_soglia);
update_post_meta($variation_id, '_backorders', $backorders);
foreach ($val as $chiave=>$valore){
$exp = explode ("*", $chiave);
$attributo_nome = $exp[0];
update_post_meta( $variation_id, 'attribute_' . $attributo_nome, $valore );
$split_attributo = explode("_", $attributo_nome);
$attributo_nome_due = $split_attributo[1];
echo "<p>Variante #$variation_id: $attributo_nome_due ($valore)</p>";
}
}
do_action( 'product_variation_linked', $variation_id );
// Update parent if variable so price sorting works and stays in sync with the cheapest child
lasap_woo_sync_varianti ($post_id, $stock_status_before);
}
delete_transient( 'wc_product_children_' . $parent_id );
UPDATING VARIATIONS (SUCH AS PRICE, SALE PRICE AND SO ON...).
$sku_arr = $_POST['sku'];
$prezzolistino_arr = $_POST['prezzolistino']; //regular_price
$prezzosaldo_arr = $_POST['prezzosaldo']; //sale_price
$datasaldoal_arr = $_POST['datasaldoal']; //sale_date_to
$datasaldodal_arr = $_POST['datasaldodal']; //sale_date_from
$manage_stock_arr = $_POST['manage_stock'];
$stock_arr = $_POST['stock'];
$stock_soglia_arr = $_POST['stock_soglia'];
$backorders_arr = $_POST['backorders'];
foreach ($sku_arr as $varID=>$sku){
$prezzolistino = $prezzolistino_arr[$varID];
$prezzosaldo = $prezzosaldo_arr[$varID];
if (($prezzosaldo!='' AND ($prezzosaldo<=$prezzolistino))){$prezzoesposto=$prezzosaldo;} else {$prezzoesposto=$prezzolistino;}
$prezzoesposto = $prezzoesposto * 1;
$datasaldoal = $datasaldoal_arr[$varID];
$datasaldodal = $datasaldodal_arr[$varID];
$manage_stock = $manage_stock_arr[$varID];
$stock = $stock_arr[$varID];
$stock_soglia = $stock_soglia_arr[$varID];
$backorders = $backorders_arr[$varID];
switch ($manage_stock){
case "on": $manage_stock = "yes"; break;
default : $manage_stock = "no";
}
switch ($backorders){
case "on": $backorders = "yes"; break;
default : $backorders = "no";
}
update_post_meta ($varID, '_sku', $sku);
update_post_meta ($varID, '_regular_price', $prezzolistino);
update_post_meta ($varID, '_sale_price', $prezzosaldo);
update_post_meta ($varID, '_price', $prezzoesposto);
update_post_meta ($varID, '_sale_price_dates_to', $datasaldoal);
update_post_meta ($varID, '_sale_price_dates_from', $datasaldodal);
update_post_meta ($varID, '_manage_stock', $manage_stock);
update_post_meta ($varID, '_stock', $stock);
update_post_meta ($varID, '_stock_soglia', $stock_soglia);
update_post_meta ($varID, '_backorders', $backorders);
}
// Update parent if variable so price sorting works and stays in sync with the cheapest child
$tipo = $_POST['tipo'];//this is a value to check if I am updating main product or its children
if ($tipo != 'parent'){
lasap_woo_sync_varianti ($post_id, $stock_status_before);
}
DELETING VARIATION(S)
$ID_arr = $_POST['ID'];
foreach ($ID_arr as $ID){
$res = wp_delete_post($ID, true);
}
$variazioni = lasap_woo_check_variazioni($post_id);
if ($variazioni > 0){
// Update parent if variable so price sorting works and stays in sync with the cheapest child
lasap_woo_sync_varianti ($post_id, $stock_status_before);
} else {
//clean up main product
delete_post_meta($post_id, '_product_attributes');
delete_post_meta($post_id, '_min_variation_price');
delete_post_meta($post_id, '_max_variation_price');
delete_post_meta($post_id, '_min_price_variation_id');
delete_post_meta($post_id, '_max_price_variation_id');
delete_post_meta($post_id, '_min_variation_regular_price');
delete_post_meta($post_id, '_max_variation_regular_price');
delete_post_meta($post_id, '_min_regular_price_variation_id');
delete_post_meta($post_id, '_max_regular_price_variation_id');
delete_post_meta($post_id, '_min_variation_sale_price');
delete_post_meta($post_id, '_max_variation_sale_price');
delete_post_meta($post_id, '_min_sale_price_variation_id');
delete_post_meta($post_id, '_max_sale_price_variation_id');
update_post_meta($post_id, '_stock_status', 'instock');
wp_set_object_terms ($post_id,'simple','product_type');
wc_delete_product_transients( $post_id );
}
FUNCTION CALLED FOR SYNCING....
function lasap_woo_sync_varianti ($post_id, $stock_status_before){
//https://docs.woocommerce.com/wc-apidocs/class-WC_Product_Variable.html
//WC_Product_Variable::variable_product_sync( $post_id );//sync variable product prices with the children lowest/highest (calls :sync)
//WC_Product_Variable::sync_stock_status( $post_id );//sync the variable product stock status with children
//WC_Product_Variable::sync_attributes( $post_id );//sync the variable product's attributes with the variations (called by :sync)
WC_Product_Variable::sync( $post_id );//sync the variable product with it's children
wc_delete_product_transients( $post_id );
lasap_get_variation_prices ($post_id);
$stock_status_after = get_post_meta($post_id, '_stock_status', true);
update_post_meta($post_id, '_stock_status', $stock_status_before);
}
FUNCTION FOR SETTING TRANSIENT (EXTRACTED FROM woocommerce\includes\class-wc-product-variable.php)
function lasap_get_variation_prices( $post_id, $display = false ) {
global $wp_filter, $woocommerce, $wpdb;
$_product = wc_get_product( $post_id );
/**
* Transient name for storing prices for this product (note: Max transient length is 45)
* #since 2.5.0 a single transient is used per product for all prices, rather than many transients per product.
*/
$transient_name = 'wc_var_prices_' . $post_id;
/**
* Create unique cache key based on the tax location (affects displayed/cached prices), product version and active price filters.
* DEVELOPERS should filter this hash if offering conditonal pricing to keep it unique.
* #var string
*/
if ( $display ) {
$price_hash = array( get_option( 'woocommerce_tax_display_shop', 'excl' ), WC_Tax::get_rates() );
} else {
$price_hash = array( false );
}
$filter_names = array( 'woocommerce_variation_prices_price', 'woocommerce_variation_prices_regular_price', 'woocommerce_variation_prices_sale_price' );
foreach ( $filter_names as $filter_name ) {
if ( ! empty( $wp_filter[ $filter_name ] ) ) {
$price_hash[ $filter_name ] = array();
foreach ( $wp_filter[ $filter_name ] as $priority => $callbacks ) {
$price_hash[ $filter_name ][] = array_values( wp_list_pluck( $callbacks, 'function' ) );
}
}
}
$price_hash = md5( json_encode( apply_filters( 'woocommerce_get_variation_prices_hash', $price_hash, $_product, $display ) ) );
// If the value has already been generated, we don't need to grab the values again.
if ( empty( $post_id->prices_array[ $price_hash ] ) ) {
// Get value of transient
$prices_array = array_filter( (array) json_decode( strval( get_transient( $transient_name ) ), true ) );
// If the product version has changed, reset cache
if ( empty( $prices_array['version'] ) || $prices_array['version'] !== WC_Cache_Helper::get_transient_version( 'product' ) ) {
$post_id->prices_array = array( 'version' => WC_Cache_Helper::get_transient_version( 'product' ) );
}
// If the prices are not stored for this hash, generate them
//if ( empty( $prices_array[ $price_hash ] ) ) {
if ( 1>0 ) {
$prices = array();
$regular_prices = array();
$sale_prices = array();
$variation_ids = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE post_type='product_variation' AND post_status='publish' AND post_parent=$post_id", 0);
foreach ( $variation_ids as $variation_id ) {
$post_meta = get_post_meta($variation_id);
$price = $post_meta['_price'][0];
$regular_price = $post_meta['_regular_price'][0];
$sale_price = $post_meta['_sale_price'][0];
// Skip empty prices
if ( '' === $price ) {
continue;
}
// If sale price does not equal price, the product is not yet on sale
if ( $sale_price === $regular_price || $sale_price !== $price ) {
$sale_price = $regular_price;
}
// If we are getting prices for display, we need to account for taxes
if ( $display ) {
if ( 'incl' === get_option( 'woocommerce_tax_display_shop' ) ) {
$price = '' === $price ? '' : $variation->get_price_including_tax( 1, $price );
$regular_price = '' === $regular_price ? '' : $variation->get_price_including_tax( 1, $regular_price );
$sale_price = '' === $sale_price ? '' : $variation->get_price_including_tax( 1, $sale_price );
} else {
$price = '' === $price ? '' : $variation->get_price_excluding_tax( 1, $price );
$regular_price = '' === $regular_price ? '' : $variation->get_price_excluding_tax( 1, $regular_price );
$sale_price = '' === $sale_price ? '' : $variation->get_price_excluding_tax( 1, $sale_price );
}
}
$prices[ $variation_id ] = wc_format_decimal( $price, wc_get_price_decimals() );
$regular_prices[ $variation_id ] = wc_format_decimal( $regular_price, wc_get_price_decimals() );
$sale_prices[ $variation_id ] = wc_format_decimal( $sale_price . '.00', wc_get_price_decimals() );
}
asort( $prices );
asort( $regular_prices );
asort( $sale_prices );
$prices_array[ $price_hash ] = array(
'price' => $prices,
'regular_price' => $regular_prices,
'sale_price' => $sale_prices,
);
echo "<br> 659) ";mostra_array($prices_array);
set_transient( $transient_name, json_encode( $prices_array ), DAY_IN_SECONDS * 30 );
}
/**
* Give plugins one last chance to filter the variation prices array which has been generated.
*/
$post_id->prices_array[ $price_hash ] = apply_filters( 'woocommerce_variation_prices', $prices_array[ $price_hash ], $post_id, $display );
}
}
FUNCTION I USE TO CHECK IF PRODUCT HAS VARIATIONS (RETURN QTY)
function lasap_woo_check_variazioni($post_id){
global $wpdb;
$qry_var=" SELECT COUNT(ID) FROM $wpdb->posts WHERE
post_type='product_variation' AND
post_parent=$post_id AND
post_status='publish'";
$res_var=$wpdb->get_var($qry_var);
return $res_var;
}
After all this, another problem rose up (it NEVER happens, doesn'it?): I haven't figured it out why but after updating variations, parent product post_meta '_stock_status' was always set as 'outofstock'.
I have patched this retrieving at the beginning the correct status with get_post_meta and passing its value to the function lasap_woo_sync_varianti.
Any improvements are greatly appreciated and hope this will help someone to save his/her time!
Tested and working on WC 2.6.13. See link here

update_post_meta( $post_id, '_visibility', PARAM' )
It will have 3 or 4 parameters: hidden | search | catalog | visible
Try to set your _visibility to "visible" param.

With the last actualization of woocommerce, This code does not work.
When I use this code :
$my_post = array(
'post_title' => 'Variation #' . $i . ' of ' . esc_attr(strip_tags($_POST['postTitle'])),
'post_name' => 'product-' . $post_id . '-variation-' . $i,
'post_status' => 'publish',
'post_parent' => $post_id,
'post_type' => 'product_variation',
'guid' => home_url() . '/?product_variation=product-' . $post_id . '-variation-' . $i
);
wp_insert_post( $my_post );
three variations are inserted by default, and I am not able to delete or insert another variation.
Any solution?

Related

WP_insert_term creating duplicate categories during WooCommerce product import

I've been racking my brain for a few days on this issue and can't figure out why my code to import is creating duplicate product categories.
Problem: I am pulling in about 30,000 products from the third party API in JSON format it is then is inserted into a custom database, from which I pull each product's data and format for importing into WooCommerce, these processes are working fine the problem comes when I am inserting the category terms. When categories are inserted using wp_insert_term some categories are duplicated but have a different URL slug.
ie...
— Ranges, Cooktops & Ovens
— — Range Hoods & Downdraft Ventilation (slug: range-hoods-downdraft-ventilation )
— — Range Hoods & Downdraft Ventilation (slug: range-hoods-downdraft-ventilation-ranges-cooktops-ovens)
The child category gets duplicated but with a different slug.
This is the Category array I'm looping through to create the hierarchical category paths:
"categoryPath":[{"id":"cat00000","name":"Company Name"},{"id":"abcat0900000","name":"Appliances"},{"id":"abcat0904000","name":"Ranges, Cooktops & Ovens"},{"id":"abcat0904002","name":"Range Hoods & Downdraft Ventilation"}]
Here is my single product import code the relevant category portion in at the bottom starting with $categoryPath, just wanted to give some context of what Im doing:
$result= $wpdb->get_var( "SELECT `results_array`
FROM $table_name
WHERE `arr_serialize2` = $textProductSku
AND `update_type` = 'create'
");
$final_product_formate_arrays = json_decode($result, true);
$post = array(
'post_title' => $final_product_formate_arrays['parent_or_simple_product']['title'],
'post_content' => $final_product_formate_arrays['parent_or_simple_product']['longDescription'],
'post_excerpt' => isset( $final_product_formate_arrays['parent_or_simple_product']['shortDescription']) ? $final_product_formate_arrays['parent_or_simple_product']['shortDescription'] : '' ,
'post_status' => "publish",
'post_parent' => '',
'post_type' => "product",
);
$post_id = wp_insert_post( $post );
if (!$post_id)
{
return false;
}
update_post_meta($post_id,'_complete_product_data',json_encode($final_product_formate_arrays));
update_post_meta($post_id, '_sku', $final_product_formate_arrays['parent_or_simple_product']['sku']);
update_post_meta( $post_id, '_visibility', 'visible' );
if($final_product_formate_arrays['parent_or_simple_product']['inStoreAvailability'] > 0)
{
update_post_meta( $post_id, '_manage_stock', "yes" );
update_post_meta( $post_id, '_stock', $final_product_formate_arrays['parent_or_simple_product']['stockQuantity'] );
update_post_meta( $post_id, '_stock_status', 'instock');
} elseif($final_product_formate_arrays['is_variation']){
update_post_meta( $post_id, '_manage_stock', "no" );
update_post_meta( $post_id, '_stock_status', 'instock');
} else {
update_post_meta( $post_id, '_manage_stock', "yes" );
update_post_meta( $post_id, '_stock_status', 'outofstock');
update_post_meta( $post_id, '_stock', 0 );
}
update_post_meta( $post_id, '_regular_price', $final_product_formate_arrays['parent_or_simple_product']['regularPrice'] );
update_post_meta( $post_id, '_sale_price', $final_product_formate_arrays['parent_or_simple_product']['salePrice'] );
update_post_meta( $post_id, '_price', $final_product_formate_arrays['parent_or_simple_product']['salePrice'] );
update_post_meta( $post_id, '_weight', $final_product_formate_arrays['parent_or_simple_product']['weight'] );
update_post_meta( $post_id, '_length', $final_product_formate_arrays['parent_or_simple_product']['depth'] );
update_post_meta( $post_id, '_width', $final_product_formate_arrays['parent_or_simple_product']['width'] );
update_post_meta( $post_id, '_height', $final_product_formate_arrays['parent_or_simple_product']['height'] );
update_post_meta( $post_id, '_wc_average_rating', $final_product_formate_arrays['parent_or_simple_product']['reviewAverage'] );
**$categoryPath = $final_product_formate_arrays['parent_or_simple_product']['categoryPath'];
if(!empty($categoryPath))
{
$parent_id='';
foreach ($categoryPath as $key => $value) {
if($key!=0) {
$new_str = str_replace( array( ',', '&' ), '-', $value['name'] );
$new_str = sanitize_title( $new_str );
$parent_term = term_exists( $parent_id, 'product_cat' ); // array is returned if taxonomy is given
if( isset( $parent_term )) {
$parent_id = $parent_term['term_id']; // get numeric term id
} else{
$parent_id = 0;
}
$term = wp_insert_term( $value['name'], 'product_cat', [
'description'=> $value['name'],
'parent' => intval( $parent_id ),
'slug' => $new_str,
]
);
if( is_wp_error( $term ) && isset( $term->error_data['term_exists'] ) )
{
$term_id = isset( $term->error_data['term_exists'] ) ? $term->error_data['term_exists'] :'';
$term_error = $term->get_error_message();
$term_error .="\n";
error_log($term_error, 3, $pluginlog);
} else if ( !is_wp_error( $term ) ) {
$new_term_id = isset( $term['term_id']) ? $term['term_id'] : '';
$term_id = $new_term_id;
}
$term_id = intval($term_id);
$parent_id = !empty($term_id)?$term_id:'';
wp_set_post_terms($post_id, $term_id, 'product_cat');**
// wp_set_object_terms($post_id, $term_id, 'product_cat');
} else {
continue;
}
}
}

How to programmatically set a term to a Woocommerce product variation?

I would like to set all variable products, when created, with the same six different variations using an already defined attribute ("bidragsstorlek"). The six variations should have different prices.
With my current code I succeded with all steps except the last one. I succefully added an attribute, six diffrent terms and six different variations. When I look in the back end panel the product variations have the prices I want, the only thing missing is to set the right term to each variation.
I know similar questions been asked before and been trying to implement those answers, but can't get it right.
$taxonomy = 'pa_bidragsstorlek';
$arrtermnames = array('50 kronor', '100 kronor', '250 kronor', '500 kronor', '1000 kronor', '5000 kronor');
$attr_data = Array(
$taxonomy=>Array(
'name' => $taxonomy,
'value' => '',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'
)
);
$newproduct = new WC_Product($product_id);
update_post_meta( $product_id, '_product_attributes', array_merge($newproduct->get_attributes(), $attr_data) );
foreach ($arrtermnames as &$value) {
$term_name = $value; // The term "NAME"
$term_slug = sanitize_title($term_name); // The term "slug"
// Check if the term exist and if not it create it (and get the term ID).
if( ! term_exists( $term_name, $taxonomy ) ){
$term_data = wp_insert_term( $term_name, $taxonomy );
$term_id = $term_data['term_id'];
} else {
$term_id = get_term_by( 'name', $term_name, $taxonomy )->term_id;
}
// get an instance of the WC_Product Object
$product = wc_get_product( $product_id );
$attributes = (array) $product->get_attributes();
// 1. If the product attribute is set for the product
if( array_key_exists( $taxonomy, $attributes ) ) {
foreach( $attributes as $key => $attribute ){
if( $key == $taxonomy ){
$options = (array) $attribute->get_options();
$options[] = $term_id;
$attribute->set_options($options);
$attributes[$key] = $attribute;
break;
}
}
$product->set_attributes( $attributes );
}
// 2. The product attribute is not set for the product
else {
$attribute = new WC_Product_Attribute();
$attribute->set_id( sizeof( $attributes) + 1 );
$attribute->set_name( $taxonomy );
$attribute->set_options( array( $term_id ) );
$attribute->set_position( sizeof( $attributes) + 1 );
$attribute->set_visible( true );
$attribute->set_variation( false );
$attributes[] = $attribute;
$product->set_attributes( $attributes );
}
$product->save();
// Append the new term in the product
if( ! has_term( $term_name, $taxonomy, $product_id ))
wp_set_object_terms($product_id, $term_slug, $taxonomy, true );
}
unset($value);
$parent_id = $product_id;
$arrprice = array(50, 100, 250, 500, 1000, 5000);
for ($x = 0; $x <= 5; $x++) {
$variation = array(
'post_title' => 'Product #' . $parent_id. $arrprice[$x],
'post_content' => '',
'post_status' => 'publish',
'post_parent' => $parent_id,
'post_type' => 'product_variation'
);
// The variation id
$variation_id = wp_insert_post( $variation );
update_post_meta( $variation_id, '_regular_price', $arrprice[$x] );
update_post_meta( $variation_id, '_price', $arrtermnames[$x] );
update_post_meta( $variation_id, '_virtual', '1' );
// Assign the size and color of this variation
update_post_meta( $variation_id, 'attribute_'.$taxonomy, $arrtermnames[$x] );
WC_Product_Variable::sync( $parent_id );
}
Right now with this code, when checking in the panel, I have a drop-down at each variation with all the terms - but none is choosen. Any idea what is missing to make each variation to be set to the right term?

Create programmatically a product using CRUD methods in Woocommerce 3

I'd like to create a new Woocommerce product programmatically with PHP code and I have tried it with the Woocommerce 3 CRUD methods:
//Woocommerce CRUD
$objProduct = new WC_Product_Simple();
$objProduct->set_name('My Product 1'); //Set product name.
$objProduct->set_status('publish'); //Set product status.
//$objProduct->set_featured(FALSE); //Set if the product is featured. | bool
$objProduct->set_catalog_visibility('visible'); //Set catalog visibility. | string $visibility Options: 'hidden', 'visible', 'search' and 'catalog'.
$objProduct->set_description('My custom long description'); //Set product description.
//$objProduct->set_short_description('My short description'); //Set product short description.
//$objProduct->set_sku('U-123'); //Set SKU
$objProduct->set_price(5.00); //Set the product's active price.
//$objProduct->set_regular_price(5.00); //Set the product's regular price.
//$objProduct->set_sale_price(); //Set the product's sale price.
//$objProduct->set_date_on_sale_from(); //Set date on sale from. | string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date.
//$objProduct->set_date_on_sale_to();//Set date on sale to. | string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date.
//$objProduct->set_manage_stock(TRUE); //Set if product manage stock. | bool
//$objProduct->set_stock_quantity(10); //Set number of items available for sale.
//$objProduct->set_stock_status('instock'); //Set stock status. | string $status 'instock', 'outofstock' and 'onbackorder'
//$objProduct->set_backorders('no'); //Set backorders. | string $backorders Options: 'yes', 'no' or 'notify'.
//$objProduct->set_sold_individually(FALSE); //Set if should be sold individually. | bool
//$objProduct->set_weight(); //Set the product's weight.
//$objProduct->set_length(); //Set the product length.
//$objProduct->set_width(); //Set the product width.
//$objProduct->set_height(); //Set the product height.
//$objProduct->set_upsell_ids($upsell_ids); //Set upsell IDs. | array $upsell_ids IDs from the up-sell products.
//$objProduct->set_cross_sell_ids($cross_sell_ids); //Set crosssell IDs. | array $cross_sell_ids IDs from the cross-sell products.
$objProduct->set_reviews_allowed(TRUE); //Set if reviews is allowed. | bool
//$objProduct->set_purchase_note($purchase_note); //Set purchase note. | string $purchase_note Purchase note.
$attribute = new WC_Product_Attribute();
$attribute->set_id(wc_attribute_taxonomy_id_by_name('pa_color')); //if passing the attribute name to get the ID
$attribute->set_name('pa_color'); //attribute name
$attribute->set_options('red'); // attribute value
$attribute->set_position(1); //attribute display order
$attribute->set_visible(1); //attribute visiblity
$attribute->set_variation(0);//to use this attribute as varint or not
$raw_attributes[] = $attribute; //<--- storing the attribute in an array
$attribute = new WC_Product_Attribute();
$attribute->set_id(25);
$attribute->set_name('pa_size');
$attribute->set_options('XL');
$attribute->set_position(2);
$attribute->set_visible(1);
$attribute->set_variation(0);
$raw_attributes[] = $attribute; //<--- storing the attribute in an array
$objProduct->set_attributes($raw_attributes); //Set product attributes. | array $raw_attributes Array of WC_Product_Attribute objects.
//$objProduct->set_category_ids($term_ids); //Set the product categories. | array $term_ids List of terms IDs.
//$objProduct->set_tag_ids($term_ids); //Set the product tags. | array $term_ids List of terms IDs.
//$objProduct->set_image_id(); //Set main image ID. | int|string $image_id Product image id.
//$objProduct->set_gallery_image_ids(); //Set gallery attachment ids. | array $image_ids List of image ids.
$new_product_id = $objProduct->save(); //Saving the data to create new product, it will return product ID.
return;
}
But I get this error:
22-Oct-2018 20:25:19 UTC] PHP Fatal error: Uncaught Error: Class 'WC_Product_Simple' not found in /home/u1771p590/domains/famyfuerza.com/public_html/store/wp-content/plugins/ff-dropship-data-scraper/ff-dropship-data-scraper.php:165
Stack trace:
- #0 /home/u1771p590/domains/famyfuerza.com/public_html/store/wp-content/plugins/ff-dropship-data-scraper/ff-dropship-data-scraper.php(233): curl_download('https://www.ban...')
- #1 /home/u1771p590/domains/famyfuerza.com/public_html/store/wp-settings.php(305): include_once('/home/u1771p590...')
- #2 /home/u1771p590/domains/famyfuerza.com/public_html/store/wp-config.php(112): require_once('/home/u1771p590...')
- #3 /home/u1771p590/domains/famyfuerza.com/public_html/store/wp-load.php(37): require_once('/home/u1771p590...')
- #4 /home/u1771p590/domains/famyfuerza.com/public_html/store/wp-admin/admin.php(31): require_once('/home/u1771p590...')
- #5 /home/u1771p590/domains/famyfuerza.com/public_html/store/wp-admin/index.php(10): require_once('/home/u1771p590...')
- #6 {main}
thrown in /home/u1771p590/domains/famyfuerza.com/public_html/store/wp-content/plugins/ff-dropship-data-scraper/ff-dropship-data-scraper.php on line 165
I have tried to include the simple product class, but that produced another error which said that another class was missing.
Does somebody know how to fix this? Or has another method to create a woocommerce product via code?
You are not accessing the WC_Product_simple instance object from your custom Dropship Data Scraper plugin.
The guilty can be mostly 2 things:
You have not installed Woocommerce.
The plugin Dropship Data Scraper is outdated and needs changes, to handle woocommerce.
Try to include the global Woocommerce object and to enable Woocommerce support in your plugin.
To create a product programmatically using CRUD methods introduced in Woocommerce 3 here is the correct way to make it work.
If you need to handle product attributes creation or product variations creation, refer to:
Create new product attribute programmatically in Woocommerce
Create programmatically a WooCommerce product variation with new attribute values
Create programmatically a variable product and two new attributes in WooCommerce
All product attributes and their term values need to be created before. Same thing for product categories and product tags.
1) The code functions:
// Custom function for product creation (For Woocommerce 3+ only)
function create_product( $args ){
if( ! function_exists('wc_get_product_object_type') && ! function_exists('wc_prepare_product_attributes') )
return false;
// Get an empty instance of the product object (defining it's type)
$product = wc_get_product_object_type( $args['type'] );
if( ! $product )
return false;
// Product name (Title) and slug
$product->set_name( $args['name'] ); // Name (title).
if( isset( $args['slug'] ) )
$product->set_name( $args['slug'] );
// Description and short description:
$product->set_description( $args['description'] );
$product->set_short_description( $args['short_description'] );
// Status ('publish', 'pending', 'draft' or 'trash')
$product->set_status( isset($args['status']) ? $args['status'] : 'publish' );
// Visibility ('hidden', 'visible', 'search' or 'catalog')
$product->set_catalog_visibility( isset($args['visibility']) ? $args['visibility'] : 'visible' );
// Featured (boolean)
$product->set_featured( isset($args['featured']) ? $args['featured'] : false );
// Virtual (boolean)
$product->set_virtual( isset($args['virtual']) ? $args['virtual'] : false );
// Prices
$product->set_regular_price( $args['regular_price'] );
$product->set_sale_price( isset( $args['sale_price'] ) ? $args['sale_price'] : '' );
$product->set_price( isset( $args['sale_price'] ) ? $args['sale_price'] : $args['regular_price'] );
if( isset( $args['sale_price'] ) ){
$product->set_date_on_sale_from( isset( $args['sale_from'] ) ? $args['sale_from'] : '' );
$product->set_date_on_sale_to( isset( $args['sale_to'] ) ? $args['sale_to'] : '' );
}
// Downloadable (boolean)
$product->set_downloadable( isset($args['downloadable']) ? $args['downloadable'] : false );
if( isset($args['downloadable']) && $args['downloadable'] ) {
$product->set_downloads( isset($args['downloads']) ? $args['downloads'] : array() );
$product->set_download_limit( isset($args['download_limit']) ? $args['download_limit'] : '-1' );
$product->set_download_expiry( isset($args['download_expiry']) ? $args['download_expiry'] : '-1' );
}
// Taxes
if ( get_option( 'woocommerce_calc_taxes' ) === 'yes' ) {
$product->set_tax_status( isset($args['tax_status']) ? $args['tax_status'] : 'taxable' );
$product->set_tax_class( isset($args['tax_class']) ? $args['tax_class'] : '' );
}
// SKU and Stock (Not a virtual product)
if( isset($args['virtual']) && ! $args['virtual'] ) {
$product->set_sku( isset( $args['sku'] ) ? $args['sku'] : '' );
$product->set_manage_stock( isset( $args['manage_stock'] ) ? $args['manage_stock'] : false );
$product->set_stock_status( isset( $args['stock_status'] ) ? $args['stock_status'] : 'instock' );
if( isset( $args['manage_stock'] ) && $args['manage_stock'] ) {
$product->set_stock_status( $args['stock_qty'] );
$product->set_backorders( isset( $args['backorders'] ) ? $args['backorders'] : 'no' ); // 'yes', 'no' or 'notify'
}
}
// Sold Individually
$product->set_sold_individually( isset( $args['sold_individually'] ) ? $args['sold_individually'] : false );
// Weight, dimensions and shipping class
$product->set_weight( isset( $args['weight'] ) ? $args['weight'] : '' );
$product->set_length( isset( $args['length'] ) ? $args['length'] : '' );
$product->set_width( isset( $args['width'] ) ? $args['width'] : '' );
$product->set_height( isset( $args['height'] ) ? $args['height'] : '' );
if( isset( $args['shipping_class_id'] ) )
$product->set_shipping_class_id( $args['shipping_class_id'] );
// Upsell and Cross sell (IDs)
$product->set_upsell_ids( isset( $args['upsells'] ) ? $args['upsells'] : '' );
$product->set_cross_sell_ids( isset( $args['cross_sells'] ) ? $args['upsells'] : '' );
// Attributes et default attributes
if( isset( $args['attributes'] ) )
$product->set_attributes( wc_prepare_product_attributes($args['attributes']) );
if( isset( $args['default_attributes'] ) )
$product->set_default_attributes( $args['default_attributes'] ); // Needs a special formatting
// Reviews, purchase note and menu order
$product->set_reviews_allowed( isset( $args['reviews'] ) ? $args['reviews'] : false );
$product->set_purchase_note( isset( $args['note'] ) ? $args['note'] : '' );
if( isset( $args['menu_order'] ) )
$product->set_menu_order( $args['menu_order'] );
// Product categories and Tags
if( isset( $args['category_ids'] ) )
$product->set_category_ids( $args['category_ids'] );
if( isset( $args['tag_ids'] ) )
$product->set_tag_ids( $args['tag_ids'] );
// Images and Gallery
$product->set_image_id( isset( $args['image_id'] ) ? $args['image_id'] : "" );
$product->set_gallery_image_ids( isset( $args['gallery_ids'] ) ? $args['gallery_ids'] : array() );
## --- SAVE PRODUCT --- ##
$product_id = $product->save();
return $product_id;
}
// Utility function that returns the correct product object instance
function wc_get_product_object_type( $type = 'simple' ) {
// Get an instance of the WC_Product object (depending on his type)
if( $type === 'variable' ){
$product = new WC_Product_Variable();
} elseif( $type === 'grouped' ){
$product = new WC_Product_Grouped();
} elseif( $type === 'external' ){
$product = new WC_Product_External();
} else {
$product = new WC_Product_Simple(); // "simple" By default
}
if( ! is_a( $product, 'WC_Product' ) )
return false;
else
return $product;
}
// Utility function that prepare product attributes before saving
function wc_prepare_product_attributes( $attributes ){
global $woocommerce;
$data = array();
$position = 0;
foreach( $attributes as $taxonomy => $values ){
if( ! taxonomy_exists( $taxonomy ) )
continue;
// Get an instance of the WC_Product_Attribute Object
$attribute = new WC_Product_Attribute();
$term_ids = array();
// Loop through the term names
foreach( $values['term_names'] as $term_name ){
if( term_exists( $term_name, $taxonomy ) )
// Get and set the term ID in the array from the term name
$term_ids[] = get_term_by( 'name', $term_name, $taxonomy )->term_id;
else
continue;
}
$taxonomy_id = wc_attribute_taxonomy_id_by_name( $taxonomy ); // Get taxonomy ID
$attribute->set_id( $taxonomy_id );
$attribute->set_name( $taxonomy );
$attribute->set_options( $term_ids );
$attribute->set_position( $position );
$attribute->set_visible( $values['is_visible'] );
$attribute->set_variation( $values['for_variation'] );
$data[$taxonomy] = $attribute; // Set in an array
$position++; // Increase position
}
return $data;
}
2) USAGE: - Example for a simple product creation with 2 product attributes "Color" and "Size":
$product_id = create_product( array(
'type' => '', // Simple product by default
'name' => __("The product title", "woocommerce"),
'description' => __("The product description…", "woocommerce"),
'short_description' => __("The product short description…", "woocommerce"),
// 'sku' => '',
'regular_price' => '5.00', // product price
// 'sale_price' => '',
'reviews_allowed' => true,
'attributes' => array(
// Taxonomy and term name values
'pa_color' => array(
'term_names' => array('Red', 'Blue'),
'is_visible' => true,
'for_variation' => false,
),
'pa_size' => array(
'term_names' => array('X Large'),
'is_visible' => true,
'for_variation' => false,
),
),
) );
// Displaying the created product ID
echo $product_id;
Tested and works using only Woocommerce 3 CRUD methods.
Another way: https://wordpress.stackexchange.com/a/137578/74284 , Use wp_insert_post function.
https://lukasznowicki.info/insert-new-woocommerce-product-programmatically/
$item = array(
'Name' => 'Product A',
'Description' => 'This is a product A',
'SKU' => '10020030A',
);
$user_id = get_current_user(); // this has NO SENSE AT ALL, because wp_insert_post uses current user as default value
// $user_id = $some_user_id_we_need_to_use; // So, user is selected..
$post_id = wp_insert_post( array(
'post_author' => $user_id,
'post_title' => $item['Name'],
'post_content' => $item['Description'],
'post_status' => 'publish',
'post_type' => "product",
) );
wp_set_object_terms( $post_id, 'simple', 'product_type' );
update_post_meta( $post_id, '_visibility', 'visible' );
update_post_meta( $post_id, '_stock_status', 'instock');
update_post_meta( $post_id, 'total_sales', '0' );
update_post_meta( $post_id, '_downloadable', 'no' );
update_post_meta( $post_id, '_virtual', 'yes' );
update_post_meta( $post_id, '_regular_price', '' );
update_post_meta( $post_id, '_sale_price', '' );
update_post_meta( $post_id, '_purchase_note', '' );
update_post_meta( $post_id, '_featured', 'no' );
update_post_meta( $post_id, '_weight', '' );
update_post_meta( $post_id, '_length', '' );
update_post_meta( $post_id, '_width', '' );
update_post_meta( $post_id, '_height', '' );
update_post_meta( $post_id, '_sku', $item['SKU'] );
update_post_meta( $post_id, '_product_attributes', array() );
update_post_meta( $post_id, '_sale_price_dates_from', '' );
update_post_meta( $post_id, '_sale_price_dates_to', '' );
update_post_meta( $post_id, '_price', '' );
update_post_meta( $post_id, '_sold_individually', '' );
update_post_meta( $post_id, '_manage_stock', 'no' );
update_post_meta( $post_id, '_backorders', 'no' );
update_post_meta( $post_id, '_stock', '' );

Unable to get WooCoommerce product variation id

I am trying to update a specific field for all variations in a product, but unfortunately, I am unable to get variation ids to go further.
Basically what I am doing is, I am trying to get each variation's stock value and if the stock value is less than zero, then I am updating a particular field with certain values (as mentioned in my code below).
I have tested this by manually inputting any custom post / variation id and is working fine, updates that particular variation id based on its stock value. All I am stuck here is I am unable to fetch the variation id by itself.
Below is the code that I am using:
global $post, $woocommerce;
$post_id = $variation->ID;
// Get specific data from the certain custom fields using get_post_meta( $post_id, $key, $single );
$stock = get_post_meta( $post_id, '_stock', true );
if ($stock < 1) {
update_post_meta( $post_id, 'cuzd-prod-general-v', '20,25' );
} else {
update_post_meta( $post_id, 'cuzd-prod-general-v', '1,5' );
}
I don't know where I am wrong to get the variation ids for this.
I was able to solve this by using below code changes:
// Values to be updated
$in_stock = '1,5';
$out_of_stock = '20,30';
// Get variations
$args = array(
'post_type' => 'product_variation',
'post_status' => array( 'private', 'publish' ),
'numberposts' => -1,
'orderby' => 'menu_order',
'order' => 'asc',
'post_parent' => $post->ID
);
$variations = get_posts( $args );
foreach ( $variations as $variation ) {
$variation_id = absint( $variation->ID );$variable_id = $this['variation_id'];
$variation_post_status = esc_attr( $variation->post_status );
$variation_data = get_post_meta( $variation_id );
$variation_data['variation_post_id'] = $variation_id;
// Get specific data from the certain custom fields using get_post_meta( $post_id, $key, $single );
$stock = get_post_meta( $variation_data['variation_post_id'], '_stock', true );
if ($stock < 1) {
update_post_meta( $variation_data['variation_post_id'], 'cuzd-prod-general-v', $out_of_stock );
} else {
update_post_meta( $variation_data['variation_post_id'], 'cuzd-prod-general-v', $in_stock );
}
}

Woocommerce newProduct() Taxonomy is Not Working

Can you show me what I'm doing wrong?
My code to add a new product to Woocommerce looks like this right now:
function newProduct( $idERP, $titulo, $conteudo, $preco, $precoDesconto, $sku, $peso, $comprimento, $largura, $altura, $estoque, $variacoes, $categorias ){
global $woocommerce;
$titulo = utf8_encode($titulo);
$conteudo = utf8_encode($conteudo);
$my_post = array(
'post_title' => $titulo,
'post_content' => $conteudo,
'post_status' => 'pending',
'post_author' => 6,
'post_type' =>'product'
);
$product_ID = wp_insert_post( $my_post );
if ( $product_ID ){
if( $preco == $precoDesconto){
add_post_meta($product_ID, '_price', $precoDesconto );
}else{
add_post_meta($product_ID, '_regular_price', $preco );
add_post_meta($product_ID, '_price', $precoDesconto );
add_post_meta($product_ID, '_sale_price', $precoDesconto );
}
add_post_meta($product_ID, '_sku', $sku );
add_post_meta($product_ID, '_weight', $peso );
add_post_meta($product_ID, '_length', $comprimento );
add_post_meta($product_ID, '_width', $largura );
add_post_meta($product_ID, '_height', $altura );
add_post_meta($product_ID, '_stock', $this->estoque($estoque) );
add_post_meta($product_ID, '_idERP', $idERP ); //ID from erp
wp_set_object_terms( $product_ID, 'variable', 'product_type' );
//wp_set_object_terms( $product_ID, $categorias, 'product_cat');
$guardaVariacoes = array();$i = 1;
foreach($variacoes as $v){
$vid = wp_insert_post(
array(
'post_title' => 'Variacao #' . $i,
'post_name' => 'product-' . $product_ID . '-variation-' . $i,
'post_status' => 'publish',
'post_parent' => $product_ID,
'post_type' => 'product_variation',
'guid' => home_url() . '/?product_variation=product-' . $product_ID . '-variation-' . $i
)
);
if( $v[1] == $v[2] ){
update_post_meta( $vid, '_regular_price', $v[1]);
}else{
update_post_meta( $vid, '_price', $v[2] );
update_post_meta( $vid, '_regular_price', $v[1]);
update_post_meta( $vid, '_sale_price', $v[2] );
}
update_post_meta( $vid, '_stock', $this->estoque($v[0]) );
update_post_meta( $vid, '_weight', $v[3]);
update_post_meta( $vid, '_width', $v[4]);
update_post_meta( $vid, '_height', $v[5]);
update_post_meta( $vid, '_length', $v[6]);
update_post_meta( $vid, '_sku', $v[8]);
update_post_meta( $vid, '_idERP', $v[9]);
foreach($v[7] as $nAtr=>$vAtr){
$nomeAtributo = strtolower(trim($nAtr));
$tt = $nomeAtributo;
if(strtolower($tt) == 'tamanho')$tt = 'pa_tamanho';
if(strtolower($tt) == 'cor')$tt = 'pa_cor';
update_post_meta( $vid, 'attribute_'.$tt, trim($vAtr));
$temp = $tt.'|'.$nAtr;
if( !array_key_exists($temp,$guardaVariacoes) ) $guardaVariacoes[$temp] = array();
$guardaVariacoes[$temp][] = $vAtr;
}
$i++;
}
$product_attributes = array();
foreach($guardaVariacoes as $r=>$s){
$r = explode('|',$r);
$temp = array();
foreach($s as $w){
$w = trim($w);
if( strtoupper($w) == 'UNICA' ){
$w = 'Única';
}
if( strtoupper($w) == 'UNICO' ){
$w = 'Único';
}
if( array_search( $w,$temp)===false){
if( strtoupper(trim($r[1])) == 'COR'){
$temp[] = ucfirst(strtolower($w));
}else{
$temp[] = $w;
}
}
}
$s = array_unique($temp);
$tt = $r[1];
if(strtolower($tt) == 'tamanho')$tt = 'pa_tamanho';
if(strtolower($tt) == 'cor')$tt = 'pa_cor';
$product_attributes[$r[0]] = array(
'name' => $tt,
'value' => implode(' | ', $s ),
'position' => 1,
'is_visible' => 1,
'is_variation' => 1,
'is_taxonomy' => 1 //MY PROBLEM IS HERE
);
}
update_post_meta($product_ID, '_product_attributes', $product_attributes);
}
return $product_ID;
}
When I change the code like so...
'is_taxonomy' => 1
...it works, but it doesn't work for "search layered filters", which means I have to use taxonomy.
How do I do that without losing the "attributes" inside my product?
Sounds to me like you are trying to set Categories for products, and correct me if I'm wrong please. If this is the case, you don't want to use taxonomies. First, you are missing a ton of meta_keys for the product and all of it's variations. I suggest you install a fresh copy of WooCommerce plugin on a Fresh copy of Wordpress. Create a product manually in the back-end with 2 variations, and take a look at the wp_posts and wp_postmeta (post_id, meta_key, and meta_values). For variations, there are more values for the actual product id in the wp_postmeta table than that of the variations. _max_variation_sale_price_id, _max_variation_sale_price, _min_variation_sale_price_id, _min_variation_sale_price, etc. etc. etc. There is also another serialized array, _default_attributes, that you can just make an empty array and serialize it, for the product so that it has it's defaults set.
So, if you are referring to Categories and want to assign products to categories so that you can click on a category and see that product in there... than do the following:
Keep is_taxonomy set to 0
is_visible doesn't matter, if you want to see it under Additional Info, than set to 1, otherwise, it should still show all different variations, but I suppose it depends on your theme's way of handling this.
position needs to start at 1 and be incremented each time, so use a variable for this, example:
$position = 1;
foreach($guardaVariacoes as $r=>$s) {
// your top code... down to where the _product_attributes array begins...
$product_attributes[$r[0]] = array(
'name' => $tt,
'value' => implode(' | ', $s),
'position' => $position,
'is_visible' => count($s) > 1 ? 0 : 1,
'is_variation' => count($s) > 1 ? 1 : 0,
'is_taxonomy' => 0
);
$position++;
}
To create and assign categories on the fly for products you use: term_exists (will return 0 or NULL if term doesn't exist, you can check with empty()), wp_insert_term (if the term doesn't exist), insert it so that you can assign the category to the product. Example below if you want to insert a sub-brand category into a parent brand category, just an example of how I add categories to products (wp_term_relationships table assigns the categories to each product, via the products/posts ID value):
// Check if Brand exists or not...
$brand = term_exists('brand', 'product_cat', 0);
$category = 'new category';
$cat_name = addslashes(ucwords(strtolower($category)));
$cats['brand'] = array(
'name' => $cat_name,
'slug' => sanitize_title_with_dashes($category)
);
if (!empty($brand))
{
$subbrand = term_exists($cats['brand']['slug'], 'product_cat', $brand['term_id']);
if (empty($subbrand))
{
$subbrand = wp_insert_term(
$cats['brand']['name'],
'product_cat',
array(
'slug' => $cats['brand']['slug'],
'parent'=> $brand['term_id']
)
);
}
} else {
$brand = wp_insert_term(
'Brand',
'product_cat',
array(
'slug' => 'brand',
'parent'=> 0 // This means it will be at the first level!
)
);
$subbrand = term_exists($cats['brand']['slug'], 'product_cat', $brand['term_id']);
if (empty($subbrand))
{
$subbrand = wp_insert_term(
$cats['brand']['name'],
'product_cat',
array(
'slug' => $cats['brand']['slug'],
'parent'=> $brand['term_id']
)
);
}
}
$categories = array(
'product_id' => // put the product id value in here!
'terms' => array()
);
if (!empty($subbrand))
{
$categories['terms']['subbrands'] = $subbrand;
}
// Now insert into term_relationships table for that product and that's all folks...
foreach($categories['terms'] as $type => $nfo)
{
$wpdb->insert(
$wpdb->prefix . "term_relationships",
array(
'object_id' => $categories['product_id'],
'term_taxonomy_id' => intval($nfo['term_taxonomy_id']),
'term_order' => 0
),
array('%d', '%d', '%d')
);
}
So, hopefully this helps you to build categories for your products, while still keeping your product attributes in tact in the search filter. Good Luck.

Categories