Search code examples
phpwordpresswoocommercecrudhook-woocommerce

WooCommerce Products attribute overwrites over older attributes when saved


I am trying to create product attribute on user input, but whenever i send the request the attribute gets created but it overrides the previous attributes linked to the product.

public static function create_variable_product(){
        $variant_data = wp_clean(isset($_POST['data']) ? wp_unslash($_POST['data']) : '');
        $product_id = wp_clean(isset($_POST['product_id']) ? wp_unslash($_POST['product_id']) : '');
        $variant_data = json_decode($variant_data);
        $product = wc_get_product($product_id);
        if($product->has_child() == false){
            $product = new WC_Product_Variable($product_id);
        }
        $attribute = self::create_product_attribute($product,$variant_data);
        
        wp_send_json($attribute);
    }
    
public static function create_product_attribute($product,$variant_data){
        
        $id = [];
        for($i=0; $i<count($variant_data); $i++){
            $attribute = new WC_Product_Attribute();
            $attribute->set_id(0);
            foreach($variant_data[$i] as $key => $value){
                
                if($key == 'attribute_name'){
                    $attribute->set_name($value);
                }
                if($key == 'options'){
                    $attribute->set_options($value);
                }
    
            }   
                $attribute->set_position( 1 );

                $attribute->set_visible( 1 );

                $attribute->set_variation( 1 );
                $attribute->is_taxonomy(0);

                $product->set_attributes(array($attribute));
                array_push($id,$product->save());
            
        }
        return $id;
}

The data being passed to $_POST['data'] is:

[{
  attribute_name: 'Color',
  options: ['red','yellow','blue']
}]

Solution

  • There are some mistakes in your code. Try the following instead (untested):

    public static function create_variable_product(){
        $data       = wp_clean(isset($_POST['data'] ? wp_unslash($_POST['data']) : '');
        $product_id = wp_clean(isset($_POST['product_id']) ? wp_clean( wp_unslash($_POST['product_id']) ) : '');
        $product    = wc_get_product($product_id);
        
        if( is_a($product, 'WC_Product') && ! $product->is_type('variable') && isset($_POST['data']) ){
            $product = new WC_Product_Variable($product_id);
        }
        
        $attribute = self::create_product_attribute($product, $data);
        $product->save()
        
        wp_send_json($attribute);
    }
    
    public static function create_product_attribute( $product, $data ) {
        $attributes = $product->get_attributes();
        $attribute  = new WC_Product_Attribute();
    
        foreach($data as $key => $values){
            if( $key === 'attribute_name'){
                $attribute->set_name($values);
            } elseif( $key === 'options' ){
                $attribute->set_options($values);
            }
        }
        $attribute->set_position( 1 );
        $attribute->set_visible( 1 );
        $attribute->set_variation( 1 );
        $attribute->is_taxonomy(0);
        
        $attributes[$attribute->get_name()] = $attribute;
    
        $product->set_attributes($attributes);
    }
    

    It should better work.