When I execute the code below, there will be added a product to WooCommerce Products with variations of the attributes 'pa_size' and 'pa_color' after I pushed a button.
When I preview the product, everything works fine.
However, when I'm going to edit and save that product, there are no attributes existing. On top of that, the variations disappear when I'm saving the product again.
I've searched the internet for at least three days, so if someone knows a proper solution I would be grateful.
Code:
class Product {
function __construct () {
// In a class constructor
$this->size_tax = wc_attribute_taxonomy_name( 'Size' );
$this->color_tax = wc_attribute_taxonomy_name( 'Color' );
}
function addProduct() {
// Insert the main product first
// It will be used as a parent for other variations (think of it as a container)
$product_id = wp_insert_post( array(
'post_title' => "Product Example",
'post_content' => "Product post content goes here...",
'post_status' => "publish",
'post_excerpt' => "This is the description",
'post_name' => "test_prod_vars2", //name/slug
'post_type' => "product"
) );
// Insert the attributes (I will be using size and color for variations)
$attributes = array(
$this->size_tax => array(
'name' => $this->size_tax,
'value' =>'',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'
),
$this->color_tax => array(
'name' => $this->color_tax,
'value' => '',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'
)
);
update_post_meta( $product_id, '_product_attributes', $attributes );
// Assign sizes and colors to the main product
// Set product type as variable
wp_set_object_terms( $product_id, 'variable', 'product_type', false );
// Start creating variations
$sizes = array('small', 'medium', 'large');
$prices = array('5', '10', '15');
$colors = array('red', 'white', 'blue');
for($i=0; $i<count($sizes); $i++) {
for($j=0; $j<count($colors); $j++) {
$parent_id = $product_id;
$variation = array(
'post_title' => 'Product #' . $parent_id . ' Variation',
'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, '_price', $prices[$i] );
// Assign the size and color of this variation
update_post_meta( $variation_id, 'attribute_' . $this->size_tax, $sizes[$i] );
update_post_meta( $variation_id, 'attribute_' . $this->color_tax, $colors[$j] );
// Update parent if variable so price sorting works and stays in sync with the cheapest child
WC_Product_Variable::sync( $parent_id );
}
}
}
}
if(isset($_POST['button'])) {
$product = new Product;
$product->addProduct();
}
If your attribute
'is_taxonomy' => '1'
then you have to insert taxonomy slug instead of text based value.
Try 'is_taxonomy' => '0' as a fast check.
Related
Inserting parent variable product first:
$parent_product = array(
'post_title' => 'Euro Washing Machine',
'post_content' => 'Some Description',
'post_type' => 'product',
'post_status' => 'publish',
'post_parent' => '',
'meta_input' => array(
'_rrp' => 220,
'_sku' =>'wedf4532d',
'_visibility' => 'visible'
)
);
$parent_product_id = wp_insert_post( $parent_product, true );
if ( ! $parent_product_id ) {
return 0;
}
wp_set_object_terms( $parent_product_id, 'variable', 'product_type' );
wp_set_object_terms( $parent_product_id, 'brand-new', 'pa_' . 'condition' );
$parent_data_attributes[ 'pa_' . 'condition' ] = array(
'name' => 'pa_' . 'condition',
'value' => 'brand-new',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'
);
update_post_meta( $parent_product_id, '_product_attributes', $parent_data_attributes );
Insert Product Variation with attribute pa_condition
$variation_product = array(
'post_title' => 'Euro Washing Machine',
'post_name' => 'product-' . $parent_product_id . '-variation',
'post_status' => 'publish',
'post_parent' => $parent_product_id,
'post_type' => 'product_variation'
);
$variation_product_id = wp_insert_post( $variation_product );
update_post_meta( $variation_product_id, '_price', 221 );
update_post_meta( $variation_product_id, '_sale_price', 221 );
update_post_meta( $variation_product_id, '_regular_price', 221 );
update_post_meta( $variation_product_id, '_manage_stock', 'true' );
update_post_meta( $variation_product_id, '_stock', 1 );
$variation = new WC_Product_Variation($variation_product_id);
$variation->set_attributes( array(
'pa_condition' => 'brand-new'
) );
$variation->save();
Programmatically added variation showing on admin area but not showing on Front-End. If I logged in to admin and just hit update the product then it appears on the front.
Can you please tell me, What I am missing here?
I got this problem due to setting up the product category on the variable product after creating all variations.
$ret = wp_set_object_terms($variable_product_id, $term_id, 'product_cat');
If I set the category on the variable product before creating all the variations then it solved the issue. Now I can see all variations on my category pages.
I am trying to add 2 product variations programmatically for a variable product.
Based on this answer thread, I am using the following shortened function:
function create_product_variation( $product_id, $variation_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()
);
$variation_id = wp_insert_post( $variation_post );
$variation = new WC_Product_Variation( $variation_id );
foreach($variation_data as $_variation_data){
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();
}
I use the following data array:
$variations_data = array(
array(
'attributes' => array(
'color' => 'Blue',
'warranty-and-insurance' => 'W1',
),
'sku' => ,
'regular_price' => 2000,
'sale_price' => 1800,
'stock_qty' => 5,
),
array(
'attributes' => array(
'color' => 'Red',
'warranty-and-insurance' => 'W1',
),
'sku' => ,
'regular_price' => 3000,
'sale_price' => 2800,
'stock_qty' => 3,
)
);
Then I run the function with the following:
create_product_variation( $variable_product_id, $variations_data );
where $variable_product_id is the id of the variable product which I want to make variations for it and $variations_data the data array defined above.
My problem is that the update_post_meta() function just insert the last data from the foreach in function.
i.e. in product variation in woocommerce there are:
Red W1
Red W1
but I want:
Blue W1
Red W1
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
Basically I'm trying to add a new bookable product in Woocommerce using a custom form I've made, so I have to add the products programmatically. Creating the product is fine, the problem is that I can't figure out how to add a new person type to my product so I can fix multiple prices.
Does someone have an idea how to do this?
This is the code I have so far.
$post_id = wp_insert_post( array(
'post_title' => $_POST["title"],
'post_content' => $_POST["description"],
'post_status' => 'publish',
'post_type' => "product",
) );
wp_set_object_terms( $post_id, 'booking', 'product_type' );
The following will enable "has persons" and create your person types for a bookable product:
// Create the product
$product_id = wp_insert_post( array(
'post_title' => $_POST["title"],
'post_content' => $_POST["description"],
'post_status' => 'publish',
'post_type' => "product",
) );
// Set the product type
wp_set_object_terms( $product_id, 'booking', 'product_type' );
// Get an instance of the WC_Product Object
$product = wc_get_product($product_id);
// Enable persons and save
$product->set_has_persons(true);
$product->save();
// Here define your person types (one array by person type)
$persons_type_data = array(
// First person type
array(
'block_cost' => 0,
'cost' => 16.50,
'description' => '',
'max' => '',
'min' => '',
'name' => __('Adults'),
),
// Second person type
array(
'block_cost' => 0,
'cost' => 9.20,
'description' => '',
'max' => '',
'min' => '',
'name' => __('Childs'),
),
);
// Loop Through persons type data
foreach( $persons_type_data as $key => $values ){
$person_type = new WC_Product_Booking_Person_Type();
$person_type->set_block_cost($values['block_cost']);
$person_type->set_cost($values['cost']);
$person_type->set_description($values['description']);
$person_type->set_max($values['max']);
$person_type->set_min($values['min']);
$person_type->set_name($values['name']);
$person_type->set_parent_id($product_id);
$person_type->set_sort_order($key); // Sorting is based on the array order
// Save the person type
$person_type->save();
// Add the person type to the array
$persons[] = $person_type;
}
// Set person types and save the product
$product->set_person_types($persons);
$product->save();
Tested and works.
I have a store with 8k products that I imported with a plugin made by me.
The products, the categories and the variations are all correct.
All shop is correct.
But the problem is the page of each category does not output the products until I give them to manually save one by one.
I have disabled the theme and the plugin and the same thing continues with the originals.
If I change the query manually by overriding the archive-product, all the products are seen, but the pagination and category listing remain the same.
Could it be for some meta-post?
Any solution?
Thank you very much to all.
My function to generate a basic and variant product:
$post = array(
'post_author' => 1,
'post_content' => $this->getDescription(),
'post_status' => 'publish',
'post_title' => $this->getName(),
'post_parent' => '',
'post_type' => 'product'
);
$postId = wp_insert_post($post);
$this->setId($postId);
if ($this->getId()) {
update_post_meta($this->getId(), '_sku', $this->getSku());
update_post_meta($this->getId(), '_visibility', 'visible');
wp_set_object_terms($postId, $this->getCategories(), 'product_cat');
$this->getImageXML();
update_post_meta($this->getId(), '_price', $this->price);
update_post_meta($this->getId(), '_regular_price', $this->price);
wp_set_object_terms($this->getId(), $this->getType(), 'product_type', false);
if ($this->getType() == 'simple') {
update_post_meta($this->getId(), '_manage_stock', 'yes');
update_post_meta($this->getId(), '_stock', $this->getStock());
} else {
$talla = wc_attribute_taxonomy_name('Größe');
$attributes = array(
$talla => array(
'name' => $talla,
'value' => '',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'
)
);
wp_set_object_terms($this->getId(), $this->getAtributos(), $talla);
update_post_meta($this->getId(), '_product_attributes', $attributes);
foreach ($this->getVariants() as $key => $variant) {
$variation = array(
'post_title' => 'Product #' . $this->getId() . ' Variation',
'post_content' => '',
'post_status' => 'publish',
'post_parent' => $this->getId(),
'post_type' => 'product_variation'
);
$variationId = wp_insert_post($variation);
update_post_meta($variationId, '_sku', $variant['ean']);
update_post_meta($variationId, '_regular_price', $this->price);
update_post_meta($variationId, '_price', $this->price);
update_post_meta($variationId, '_manage_stock', 'yes');
update_post_meta($variationId, '_stock', $variant['stock']);
if ($variant['stock'] > 0) {
update_post_meta($variationId, '_stock_status', 'instock');
} else {
update_post_meta($variationId, '_stock_status', 'outofstock');
}
update_post_meta($variationId, 'attribute_' . $talla, strtolower(str_replace('/', '', $variant['talla'])));
}
WC_Product_Variable::sync($this->getId());
WC_Product_Variable::sync_attributes($this->getId());
}
}
I found the solution to my problem:
Add this two meta_tags to product:
update_post_meta($yourID, 'total_sales', 0);
update_post_meta($yourID, '_stock_status', 'instock');
or
update_post_meta($yourID, 'total_sales', 0);
update_post_meta($yourID, '_stock_status', 'outofstock');
In my case total_sale is 0 because they are new products.
add_action( 'init', 'add_product_to_cart' );
function add_product_to_cart() {
if ( isset($_POST['mix']) && !empty($_POST['mix']) && isset($_POST['mix_name']) && !empty($_POST['mix_name']) ) {
global $woocommerce;
$mix_name = $_POST['mix_name'];
$my_post = array(
'post_title' => $mix_name,
'post_content' => 'A mix by Customer',
'post_status' => 'publish',
'post_author' => 1,
'post_type' =>'product'
);
// Insert the post into the database
$product_ID = wp_insert_post( $my_post );
$term = get_term_by('name', 'Mix', 'product_cat');
wp_set_object_terms($product_ID, $term->term_id, 'product_cat');//set category for this product
// Set product type as variable
wp_set_object_terms( $product_ID, 'variable', 'product_type' , false);
$attributes = array(
'strain'=>array(
'name'=>'strain',
'value'=>'',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'),
'level'=>array(
'name' => 'level',
'value' => '',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'
)
);
update_post_meta( $product_ID, '_product_attributes', $attributes );
// Assign sizes and colors to the main product
wp_set_object_terms( $product_ID, array( 'black berry kush', 'la confidential' ), 'strain' );
wp_set_object_terms( $product_ID, array( 'thc 30%', 'thc 20%' ) , 'level' );
// 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 = $product_ID;
$variation = array(
'post_title' => 'Product #' . $parent_id . ' Variation',
'post_content' => '',
'post_status' => 'publish',
'post_parent' => $parent_id,
'post_type' => 'product_variation'
);
// The variation id
$variation_id = wp_insert_post( $variation );
if ( $product_ID ){
add_post_meta($product_ID, '_regular_price', 100 );
add_post_meta($product_ID, '_price', 100 );
add_post_meta($product_ID, '_stock_status', 'instock' );
// Assign the size and color of this variation
update_post_meta( $variation_id, 'attribute_strain', 'black berry kush' );
update_post_meta( $variation_id, 'attribute_level', 'thc 20%' );
update_post_meta( $variation_id, '_regular_price', 100 );
update_post_meta( $variation_id, '_price', 100 );
update_post_meta($variation_id, '_stock_status', 'instock' );
update_post_meta($variation_id, '_visibility', 'visible' );
//Getting error on this line.
$addcart = $woocommerce->cart->add_to_cart( $product_ID, $variation_id, $quantity=1 );
if($addcart) {
wp_safe_redirect( WC()->cart->get_checkout_url() );
exit;
} else {
wc_print_notices();
_e('Can\'t add');
}
}
}
}
I create a function to create a variation product to add to the cart when The button is clicked. I don't know what wrong with the code but it's said
Sorry, this product cannot be purchased.
If add to cart for with only $product_ID, it's successful but when it is with $variation_ID, it return false. Can someone tell me how to set the attribute for the variation product.
Thanks a lot