WordPress Woocommerce – use update_post_meta to add product attributes

The products in my clients website require certain attributes which I have added via Products -> Attributes in the WordPress administration. In this import script I’m coding I need to use the function update_post_meta($post_id, $meta_key, $meta_value) to import the proper attributes and values.

Currently I have the function like so:

Read More
update_post_meta( $post_id, '_product_attributes', array());

However I’m not sure how to properly pass along the attributes and their values?

Related posts

Leave a Reply

4 comments

  1. Right so it took me a while to figure it out myself but I finally managed to do this by writing the following function:

    // @param int $post_id - The id of the post that you are setting the attributes for
    // @param array[] $attributes - This needs to be an array containing ALL your attributes so it can insert them in one go
    function wcproduct_set_attributes($post_id, $attributes) {
        $i = 0;
        // Loop through the attributes array
        foreach ($attributes as $name => $value) {
            $product_attributes[$i] = array (
                'name' => htmlspecialchars( stripslashes( $name ) ), // set attribute name
                'value' => $value, // set attribute value
                'position' => 1,
                'is_visible' => 1,
                'is_variation' => 1,
                'is_taxonomy' => 0
            );
    
            $i++;
        }
    
        // Now update the post with its new attributes
        update_post_meta($post_id, '_product_attributes', $product_attributes);
    }
    
    // Example on using this function
    // The attribute parameter that you pass along must contain all attributes for your product in one go
    // so that the wcproduct_set_attributes function can insert them into the correct meta field.
    $my_product_attributes = array('hdd_size' => $product->hdd_size, 'ram_size' => $product->ram_size);
    
    // After inserting post
    wcproduct_set_attributes($post_id, $my_product_attributes);
    
    // Woohay done!
    

    I hope this function will help other people if they need to import multiple attributes pro-grammatically in WooCommerce!

  2. I tried Daniel’s answer, and it didn’t work for me. It might be that the WordPress/Woocommerce code has changed since, or perhaps I didn’t quite understand how to do it, but either way that code did nothing for me. After a lot of work using it as a base, however, I came up with this snippet of code and put it on my theme’s functions.php:

    function wcproduct_set_attributes($id) {
    
        $material = get_the_terms( $id, 'pa_material');
    
        $material = $material[0]->name;
    
        // Now update the post with its new attributes
        update_post_meta($id, '_material', $material);
    
    }
    
    // After inserting post
    add_action( 'save_post_product', 'wcproduct_set_attributes', 10);
    

    With this, I can take what I set as “material” on my WooCommerce install as a custom attribute and add it to the formal meta as _material. This in turn allows me to use another snippet of code so the WooCommerce search function extends to meta fields, meaning I can search for a material in the WooCommerce search field and have all items with that material appear.

    I hope this is useful to somebody.

  3. @Daniels’s answer works, won’t decide on right or wrong, however if you want to add the values as a taxonomy term under attributes you have to adapt the code as below (set is_taxonomy = 1). Otherwise Woocommerce sees it as custom meta field(?). It still adds the value under attributes. This will only work for strings. For values that are arrays the code has to be adapted.

    Additionally it uses the wp_set_object_terms that @Anand suggests as well. I was using that, because all the documentation I could find led to believe that had to be used. However if one only uses the wp_set_object_terms then I couldn’t see the attributes in the edit product screen. Using the information from both answers and reading on the subject resulted in the solution.

    You will need to tweak the code for things such as product variations.

    /*
     * Save Woocommerce custom attributes
     */
    
    function save_wc_custom_attributes($post_id, $custom_attributes) {
        $i = 0;
        // Loop through the attributes array
        foreach ($custom_attributes as $name => $value) {
            // Relate post to a custom attribute, add term if it does not exist
            wp_set_object_terms($post_id, $value, $name, true);
            // Create product attributes array
            $product_attributes[$i] = array(
                'name' => $name, // set attribute name
                'value' => $value, // set attribute value
                'is_visible' => 1,
                'is_variation' => 0,
                'is_taxonomy' => 1
            );
            $i++;
        }
        // Now update the post with its new attributes
        update_post_meta($post_id, '_product_attributes', $product_attributes);
    }
    

    Then call the function:

       $custom_attributes = array('pa_name_1' => $value_1, 'pa_name_2' => $value_2, 'pa_name_3' => $value_3);
       save_wc_custom_attributes($post_id, $custom_attributes);
    

    Thank you for posting the code Daniel & Anand. It helped me a great deal.

  4. Don’t know if this is the “correct” way to do this… But I needed a function to add ACF repeater fields with a date value as a attribute on post save, so this was the function I came up with:

    add_action( 'save_post', 'ed_save_post_function', 10, 3 );
    
    function ed_save_post_function( $post_ID, $post, $update ) {
      //print_r($post);
      if($post->post_type == 'product')
        {
         $dates = get_field('course_dates', $post->ID);
         //print_r($dates);
         if($dates)
           {
            $date_arr = array();
            $val = '';
            $i = 0;
            foreach($dates as $d)
                   {
                     if($i > 0)
                       {
                        $val .= ' | '.date('d-m-Y', strtotime($d['date']));   
                       }
                   else{
                        $val .= date('d-m-Y', strtotime($d['date']));
                       } 
                     $i++;  
                   }
                $entry = array(
                               'course-dates' => array(
                                                       'name' => 'Course Dates',
                                                       'value' => $val,
                                                       'position' => '0',
                                                       'is_visible' => 1,
                                                       'is_variation' => 1,
                                                       'is_taxonomy' => 0
                                                      )
                              );
                    update_post_meta($post->ID, '_product_attributes', $entry);
           }
        }
    }
    

    Hope this helps someone.