2

This is starting to give me a headache so hope someone here can help me and together we can help others with the same problem!

I built a plugin which generates product variations for WooCommerce automatically. This all seems to work fine except for one thing. New variations are not visible in the frontend and when I look at the product edit page they are listed like this:

Product variations wrong

When I hit the Update button and save the product, it gets magically fixed. Variations are visible in the frontend and in the back they look like this now:

Product variations correct

The code

// Get the Variable product object (parent)
$product = wc_get_product($parent_id);

$variation_post = array(
    'post_title'  => $product->get_title(),
    'post_name'   => 'product-'.$parent_id.'-variation',
    'post_status' => ($enable_variations == "yes") ? 'publish' : 'private',
    'post_parent' => $parent_id,
    'post_type'   => 'product_variation',
    'guid'        => $product->get_permalink()
);

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

$fields = array(
    '_manage_stock'                 => 'yes',
    '_backorders'                   => $backorders,
    '_stock_status'                 => $stock_status,
    '_stock'                        => $stock,
    '_regular_price'                => $price,
    '_price'                        => $price,
);

foreach ( $fields as $meta_key => $meta_value ) {
    update_post_meta($variation_id, $meta_key, $meta_value);
}

// Add attribute 1 to variation
wp_set_post_terms( $variation_id, sanitize_title($attribute_value), "pa_attribute_1", true );
update_post_meta( $variation_id, 'attribute_pa_attribute_1', sanitize_title($attribute_value));

// Add attribute 2 to variation
wp_set_post_terms( $variation_id, sanitize_title($attribute_value), "pa_attribute_2", true );
update_post_meta( $variation_id, 'attribute_pa_attribute_2', sanitize_title($attribute_value));

// Add attribute 3 to variation
wp_set_post_terms( $variation_id, sanitize_title($attribute_value), "pa_attribute_3", true );
update_post_meta( $variation_id, 'attribute_pa_attribute_3', sanitize_title($attribute_value));

wc_delete_product_transients($variation_id);

What am I missing? What happens when you click Update at a product? Already tried to use $product->save() and deleting transients like answered in most topics on the web.

4
  • some here..., Did you find any solution?
    – aidinMC
    Commented Jul 29, 2019 at 23:46
  • Yes it works now, I'll edit the post with the answer
    – Mike
    Commented Jul 31, 2019 at 8:40
  • Is there a way to know how you solve it, I have the same problem but the solution proposed doesn't solve my problem. Commented Mar 24, 2021 at 0:38
  • I've just updated the answer. The code stopped working after an update but works again with the update below.
    – Mike
    Commented Mar 31, 2021 at 16:16

1 Answer 1

1

I figured out that this happened because the attributes did not exist in WooCommerce yet. First you have to add all attributes and their values, then generate and add variations. Then it should work:

// Create an array of the attributes we want to add
$attributes = array(
    "attribute_1" => array(
        "slug"  => "attribute_1",
        "label" => "Name of attribute 1",
    ),
    "attribute_2" => array(
        "slug"  => "attribute_2",
        "label" => "Name of attribute 2",
    ),
    "attribute_3" => array(
        "slug"  => "attribute_3",
        "label" => "Name of attribute 3",
    ),
);

// Add the attributes to WooCommerce
foreach($attributes as $attribute){

    if(!get_taxonomy("pa_" . $attribute["slug"])) {
        $result = wc_create_attribute(array(
            "name" => $attribute["label"],
            "slug" => $attribute["slug"], 
            "type" => "select",
        ));
    }
    
}

// Create an array with all the terms
$attributes_values["attribute_1"] = array("value 1", "value 2", "value 3");
$attributes_values["attribute_2"] = array("value 1", "value 2", "value 3");
$attributes_values["attribute_3"] = array("value 1", "value 2", "value 3");

// Iterate over our attributes map,containing attributes that we want to sync
foreach($attributes_values as $attribute => $values ){
    // Iterate over possible values for the attribute and insert them. 
    foreach($values as $value) {
        if(!term_exists($value, wc_attribute_taxonomy_name($attribute))){
            wp_insert_term($value, wc_attribute_taxonomy_name($attribute), array('slug' => sanitize_title($term)));
        }
    }
}

Update march 2021 The above stopped working after a WooCommerce update earlier this year and figured out that it's actually possible and a lot safer to manage a varation through the WooCommerce class:

// Get the Variable product object (parent)
$product = wc_get_product($variableProductID);
   
$variation_post = array(
    'post_title'  => $product->get_title(),
    'post_name'   => 'product-'.$variableProductID.'-variation',
    'post_status' => 'publish',
    'post_parent' => $variableProductID,
    'post_type'   => 'product_variation',
    'guid'        => $product->get_permalink()
);

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

if (is_wp_error($variation_id)) {
    // Error handling
}

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

// Add attributes to variation
update_post_meta($variation_id, 'attribute_pa_device_brand', sanitize_title($action["arguments"]["device_brand"]));
update_post_meta($variation_id, 'attribute_pa_device_model', sanitize_title($action["arguments"]["device_model"]));
update_post_meta($variation_id, 'attribute_pa_case_type_colour', sanitize_title($action["arguments"]["case_type_colour"]));

$variation->set_price($action['arguments']['price']);
$variation->set_regular_price($action['arguments']['price']);
$variation->set_stock_quantity($action['arguments']['stock']);
$variation->set_manage_stock(true);
$variation->set_stock_status();
$variation->set_backorders($action['arguments']['backorders']);

$variation->save();
4
  • This answer is wrong, and ends up creating a new attribute each time. Maybe check your code before providing false answers that destroy peoples live sites. Commented Aug 17, 2020 at 1:16
  • No it doesn't. The code checks if both a term and a taxonomy exist before adding it. You probably missed something when implementing it. Also, test your code before publishing it to a live site. Especially when you're just copy pasting
    – Mike
    Commented Aug 18, 2020 at 6:57
  • Sometimes as a developer, you don't have the luxury of not working live. How people develop does not make your answer less irresponsible as yes, it indeed does NOT check. Commented Aug 20, 2020 at 5:20
  • Working on a live site is a decision, doesn't have anything to do with luxury. Nevertheless, if you have a better answer why not add that here? Help the community instead of complaining :)
    – Mike
    Commented Aug 21, 2020 at 9:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.