• Resolved mgrandbois1

    (@mgrandbois1)


    I am struggling to create product variations programmatically. I wrote a script that creates WooCommerce products based on information from an API call. Everything works except for one issue regarding product variation attributes.

    The problem I am facing is that when my variations are created, the attributes are not assigned, like so:

    My desired outcome is for the attributes to be populated. I am assigning taxonomy attributes to the parent product and their values are showing up just fine, like so:

    But when using this code to set attributes for my variation:

    // set attributes
    // $pa_format_term->term_id = integer; ID of term
    // $pa_condition_term->term_id = integer; ID of term
    $variation->set_attributes( 
        array( 
    	'pa_format' => $pa_format_term->term_id,
    	'pa_condition' => $pa_condition_term->term_id
        )
    );

    The problem where the attributes are not assigned to the variation persists. When I click to edit the WooCommerce product after my full script runs, a popup message is displayed that says, “Adding attributes failed,” which I’m assuming pertains to my issue.

    I have tried everything I know of, read dozens of forum posts, pages, etc., and still can’t get this to work. I have tried using the term ‘name’ instead of the ID, which neither works for me.

    Here is my full function for reference:

    // Create a new product action
    add_action( 'init', 'create_new_woocommerce_product');
    function create_new_woocommerce_product() {
    				
    	global $woo_product_meta;
    				
    	// Download featured image				
    	$image_data = @file_get_contents($woo_product_meta['image']);
    	if($image_data) {
    		$filename = basename($woo_product_meta['image']);
    		$upload_file = wp_upload_bits($filename, null, $image_data);
    		if (!$upload_file['error']) {
    			$wp_filetype = wp_check_filetype($filename, null);
    			$attachment = array(
    				'post_mime_type' => $wp_filetype['type'],
    				'post_title' => sanitize_file_name($filename),
    				'post_content' => '',
    				'post_status' => 'inherit'
    			);
    			$attachment_id = wp_insert_attachment( $attachment, $upload_file['file']);
    			if (!is_wp_error($attachment_id)) {
    				require_once(ABSPATH . "wp-admin" . '/includes/image.php');
    				$attachment_data = wp_generate_attachment_metadata( $attachment_id, $upload_file['file'] );
    				wp_update_attachment_metadata( $attachment_id,  $attachment_data );
    			}
    		}
    	}
    
    	// Create a new variable product
    	$product = new WC_Product_Variable();
    				
    	// set title
    	$product->set_name( $woo_product_meta['title'] );
    				
    	// set tags if they exist
    	$tag_ids = array_map(
    		function ($subject) {
    			// remove unwanted symbols in tags
    			$subject_str = str_replace(array(',', '&', '+', '-', '--', '=', ':', '.', '/', '\\', '@', '#', '$', '%', '^', '*', '(', ')', '[', ']', '{', '}', '\'', '"'), array(' ', ' and ', ' and ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '), $subject);
    			// remove multiple spaces in a row if found
    			$subject_str = preg_replace('/\s+/', ' ', $subject_str);
    			// convert tags to lowercase
    			$subject_str = strtolower($subject_str);
    			$term = get_term_by('name', $subject_str, 'product_tag');
    			// if term exists
    			if ( $term instanceof WP_Term ) {
    				return (int) $term->term_id;
    			}
    			// if term doesn't exist
    			else {
    				if ( $subject_str !== '' ) {
    					wp_create_term($subject_str, 'product_tag');
    					// get new tag and set var
    					$new_tag = get_term_by('name', $subject_str, 'product_tag');
    
    					if ($new_tag instanceof WP_Term) {
    						// set var to id val of tag
    						return (int) $new_tag->term_id;
    					} else {
    						echo 'Notice: "' . $subject_str . '" was not created. Another tag exists that is too similar.';
    					}
    				} else {
    					echo 'Notice: a tag input was blank and was skipped; cannot create a blank tag.';
    				}
    			}
    		},
    		$woo_product_meta['subjects']
    	);				
    	$product->set_tag_ids( $tag_ids );
    
    	// Set featured image
    	$product->set_image_id($attachment_id);
    				
    	// save progress
    	$product->save();
    				
    	// set author(s)
    	if ( isset($woo_product_meta['author']) ) {
    		foreach ( $woo_product_meta['author'] as $author ) {
    			// Check if there is a ',' in the author name
    			if ( strpos($author, ',') !== false ) {
    				// Get the last name
    				$woo_meta_author_last_name = substr($author, 0, strpos($author, ','));
    				// Set the full author name by swapping the first name and last name and removing the comma
    				$woo_meta_author_full_name = substr($author, (strpos($author, ',') + 1)) . " " . $woo_meta_author_last_name; 
    			} else {
    				// Set the full name
    				$woo_meta_author_full_name = $author;
    				// Get the last word and set it as the last name
    				$woo_meta_author_last_name = substr(strrchr($author, " "), 1); 
    			}
    
    			// Check if the authors taxonomy exists
    			if ( term_exists( $woo_meta_author_full_name, 'authors' ) ) {
    				// Assign the existing taxonomy item to the product
    				wp_set_object_terms( $product->get_id(), $woo_meta_author_full_name, 'authors', true );
    				// save progress
    				$product->save();
    			} else {
    				// Create a new taxonomy item and assign it to the product
    				wp_insert_term( $woo_meta_author_full_name, 'authors', array( 'slug' => sanitize_title( $woo_meta_author_full_name ) ) );
    				wp_set_object_terms( $product->get_id(), $woo_meta_author_full_name, 'authors', true );
    				// save progress
    				$product->save();
    			}
    
    		}
    	}
    				
    	// Set product attributes
    	$attributes = array();
    
    	// add the format attribute
    	$attribute = new WC_Product_Attribute();
    	$attribute->set_id( wc_attribute_taxonomy_id_by_name( 'pa_format' ) );
    	$attribute->set_name( 'pa_format' );
    	// see if current format attribute exists and set as var
    	$pa_format_term = get_term_by('name', $woo_product_meta['format'], 'pa_format');
    	if(!$pa_format_term){
    		// create new pa_format term 
    		wp_insert_term(
    			$woo_product_meta['format'], // the term 
    			'pa_format' // the taxonomy
    		);
    		$pa_format_term = get_term_by('name', $woo_product_meta['format'], 'pa_format');
    		echo 'Created new term for pa_format: ' . $pa_format_term->name;
    	} else {
    		echo 'Existing pa_format term detected: ' . $pa_format_term->name;
    	}
    	$attribute->set_options( array( $pa_format_term->term_id ) );
    	$attribute->set_position( 0 );
    	$attribute->set_visible( true );
    	$attribute->set_variation( true );
    	$attribute->is_taxonomy( true );
    	$attributes[] = $attribute;
    				
    	// add the condition attribute
    	$attribute = new WC_Product_Attribute();
    	$attribute->set_id( wc_attribute_taxonomy_id_by_name( 'pa_condition' ) );
    	$attribute->set_name( 'pa_condition' );
    	// see if current condition attribute exists and set as var
    	$pa_condition_term = get_term_by('name', $woo_product_meta['condition'], 'pa_condition');
    	if(!$pa_condition_term){
    		// create new pa_format term 
    		wp_insert_term(
    			$woo_product_meta['condition'], // the term 
    			'pa_condition' // the taxonomy
    		);
    		$pa_condition_term = get_term_by('name', $woo_product_meta['condition'], 'pa_condition');
    		echo 'Created new term for pa_condition: ' . $pa_condition_term->name;
    	} else {
    		echo 'Existing pa_condition term detected: ' . $pa_condition_term->name;
    	}
    	$attribute->set_options( array( $pa_condition_term->term_id ) );
    	$attribute->set_position( 1 );
    	$attribute->set_visible( true );
    	$attribute->set_variation( true );
    	$attribute->is_taxonomy( true );
    	$attributes[] = $attribute;
    				
    	$product->set_attributes( $attributes );
    				
    	// save the changes and go on
    	$product->save();
    				
    	// create product variation
    	$variation = new WC_Product_Variation();
    	$variation->set_parent_id( $product->get_id() );
    	$variation->set_regular_price( $woo_product_meta['price'] );
    	
    	$variation->save();
    	
    	// set attributes
    	$variation->set_attributes( 
    		array( 
    			'pa_format' => $pa_format_term->term_id,
    			'pa_condition' => $pa_condition_term->term_id
    		)
    	);
    				
    	$variation->save();
    	
    	// echo variation data for debugging purposes
    	$variation_data = $variation->get_data();
    	echo '<pre>'; 
    	print_r($variation_data);
    	echo '</pre>';
    				
    	$variation->set_image_id( $attachment_id );
    	$variation->set_description( $woo_product_meta['description'] );
    				
    	$variation->set_sku( $woo_product_meta['isbn13'] );
    	$variation->set_manage_stock( true );
    	$variation->set_stock_quantity( 0 );
    	$variation->set_backorders( 'notify' ); // 'yes', 'no' or 'notify'
    	$variation->save();
    
    	// Set the custom fields on the variation
    	$variation_id = $variation->get_id();				
    	$variation->update_meta_data('_isbn10_field', sanitize_text_field( $woo_product_meta['isbn10'] ) );
    	$variation->update_meta_data('_isbn13_field', sanitize_text_field( $woo_product_meta['isbn13'] ) );
    	$variation->update_meta_data('_language_field', sanitize_text_field( $woo_product_meta['language'] ) );
    	$variation->update_meta_data('_release_field', sanitize_text_field( $woo_product_meta['date'] ) );
    	$variation->update_meta_data('_publisher_field', sanitize_text_field( $woo_product_meta['publisher'] ) );
    	$variation->update_meta_data('_length_field', sanitize_text_field( $woo_product_meta['length'] ) );
    				
    	// Save the variation  
    	$variation->save();
    				
    	// Save the product
    	$product->save();
    				
    	// show success message
    	echo '<div>Successfully imported: ' . $woo_product_meta['title'] . '<div>';
    	do_action( 'create_new_woocommerce_product' );
    }

    Please help me resolve this issue and let me know what other code snippets and information you might need. Thank you in advance!

    Specifications:

    • PHP 8.0.29
    • WordPress 6.2.2
    • WooCommerce 7.8.0
Viewing 4 replies - 1 through 4 (of 4 total)
  • Hi @mgrandbois1,

    I did not go through your code entirely, but as per my understanding, you want to populate the attribute values when creating product variations programmatically.

    The main thing to note here is that once you fetch the names of the attribute terms by ID, you need to set the attribute values to the product variation as:

    $product_variation->add_meta_data( 'attribute_pa_format', 'Paperback' );
    
    $product_variation->add_meta_data( 'attribute_pa_condition', 'Very Good' );
    
    $product_variation->save();

    I hope this helps!

    Thread Starter mgrandbois1

    (@mgrandbois1)

    @kaavyaiyer Thank you so much for taking the time to help me. Unfortunately, this does not fix the issue. After running my script and checking the product, it still does not assign the attributes to the variation and gives me a popup notice saying, “Adding attributes failed”

    Just for clarification, would I still need to set the attributes using set_attributes() in addition to your method? Thank you!

    • This reply was modified 1 year, 5 months ago by mgrandbois1.
    Thread Starter mgrandbois1

    (@mgrandbois1)

    I FINALLY found a solution to my own problem so I wanted to share it in case it helps anyone else in the future.

    In my case, using the pa_taxonomy term name and ID did not work. So, I did some experimenting and learned that the slug does work. I changed my code from this:

    // set attributes
    // $pa_format_term->term_id = integer; ID of term
    // $pa_condition_term->term_id = integer; ID of term
    $variation->set_attributes( 
        array( 
    	'pa_format' => $pa_format_term->term_id,
    	'pa_condition' => $pa_condition_term->term_id
        )
    );

    To this:

    $variation->set_attributes( 
        array( 
    	'pa_format' => $pa_format_term->slug, // Use slug instead of term_id or name
    	'pa_condition' => $pa_condition_term->slug // Use slug instead of term_id or name
        )
    );

    Hi @mgrandbois1

    I’m glad you were able to find a solution to your inquiry here and thanks for sharing it with the community too! 🙂

    Thanks!

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘How to Create Product Variations Programmatically Using Taxonomy Attributes’ is closed to new replies.