I use following code to add attributes to a product:
foreach ($_attributes as $name => $value) {
wp_set_object_terms($post_id, $value, $name, true);
$product_attributes[$name] = array (
'name' => $name, // set attribute name
'value' => $value, // set attribute value
'is_visible' => 0,
'is_variation' => 1,
'is_taxonomy' => 1
);
}
update_post_meta($post_id, '_product_attributes', $product_attributes );
but it remove previous attributes I added in product edit in admin, like product brand or model.
How can I update current product attributes without remove previous ones?
Thanks to help me.
You could simply backup your DB content before updating, like this:
$tmpBk = get_post_meta($post_id, '_product_attributes',true);
update_post_meta($post_id, '_product_attributes', array_merge(tmpBk,$product_attributes) );
that should be enough to save your previously stored values
Related
I am trying to alter an attribute when the user saves a new product or updates an existing. If the product is a certain category the 'weight' should be N/A..
Here is my product as it should start which is fine. Now I want to add a weight field to it (Which already exists as an attribute) and assign the weight to N/A. Here's the end result I want to do programmatically.
Here is as far as I can get:
add_action( 'woocommerce_update_product', 'mp_sync_on_product_save', 10, 1 );
function mp_sync_on_product_save( $product_id ) {
$product = wc_get_product( $product_id );
if($product->category_ids[0] == 18) {
//We are jewellery
$post_id = $product->get_id();
$product_attr = get_post_meta($post_id, '_product_attributes',true);//get the whole product attributes first
$product_attr['pa_weight'] = array(
'name' => 'pa_weight',
'value' => 'N/A',
'position' => 1,
'is_visible' => 1,
'is_variation' => 1,
'is_taxonomy' => '1'
);
update_post_meta($post_id , '_product_attributes',$product_attr);
}
}
Currently nothing seems to happen here. I hope I'm close so any help to get this over the line would be awesome.
Thanks
I have created a registration form (using plugin ultimate-member) for a partner as a salesperson. The key here is:
Label : Registration Number
Meta : 'regno'
Value : X123W
So, each new registrant will get a different value as a salesperson unique ID .
On the other hand, I have created a product which is divided into 3 packages, separated by attribute with values 'pa_silver', 'pa_gold', and 'pa_diamond'.
'pa_silver' & 'pa_gold' => self-sold product (no salesperson required)
'pa_diamond' => product entrusted for selling (using salesperson).
Then on products that have taxonomy 'pa_diamond' I've added the attribute:
Label : List
tax : 'pa_list'
value : 'X123W', 'X234W' => this has been created manually.
Targets : What I want is that every time someone registers as a partner, the partner code should be "added" automatically on existing attribute ('pa_list') and on products that have taxonomy 'pa_diamond'.
I'm trying something, like:
$users = get_users( array( 'role' => array( 'partner' ) ) );
foreach($users as $user){
$regno = get_the_author_meta( 'regno', $user->ID);
echo $regno;
}
Note : it output like this => X345WX456W (2 New partner code)
Tried using the code I got from #LoicTheAztec's answer here.
The code is :
$product_id = get_the_ID();
$taxonomy = 'pa_list';
$clean_keywords = array('X345W','X456W');
$term_taxonomy_ids = wp_set_object_terms( $product_id, $clean_keywords, $taxonomy, true );
// Get existing attributes
$product_attributes = get_post_meta( $product_id, '_product_attributes', true);
// get the count of existing attributes to set the "position" in the array
$count = count($product_attributes);
// Insert new attribute in existing array of attributes (if there is any)
$product_attributes[$taxonomy] = array(
'name' => $taxonomy,
'value' => '',
'position' => $count, // added
'is_visible' => '0',
'is_variation' => '0', // added (set the right value)
'is_taxonomy' => '1'
);
// Save the data
update_post_meta( $product_id, '_product_attributes', $product_attributes );
Note : I replaced (manually) $taxonomy -> 'pa_list' and $clean_keywords = array('X345W','X465W');
In attribute field 'pa_list' both partner codes have been added but do not fill or set to product.
I'm having a hard time connecting some logic here.
I hit a dead end to get what I wanted.
Can anyone help me?
Thank You
I have a product attribute variation which has options of -
small - $20
medium - $25
large - $30
Since all the products in the store has the same price for this variations.
How to set the price for the attribute values programmatically?
3 attribute variation buttons are show on product page when I add them as variations.
How to change the price of product when "small" option is selected programmatically instead of setting price in variation options in admin panel.
As Per our understanding to want to add products with different sizes and different prices.
There is 2 way:
1. You can add from woocommerece dashboard like this:
https://www.ostraining.com/blog/woocommerce/product-variations/
You can add programmatically like this:
function insert_product ($product_data)
{
$post = array( // Set up the basic post data to insert for our product
'post_author' => 1,
'post_content' => $product_data['description'],
'post_status' => 'publish',
'post_title' => $product_data['name'],
'post_parent' => '',
'post_type' => 'product'
);
$post_id = wp_insert_post($post); // Insert the post returning the new post id
if (!$post_id) // If there is no post id something has gone wrong so don't proceed
{
return false;
}
update_post_meta($post_id, '_sku', $product_data['sku']); // Set its SKU
update_post_meta( $post_id,'_visibility','visible'); // Set the product to visible, if not it won't show on the front end
wp_set_object_terms($post_id, $product_data['categories'], 'product_cat'); // Set up its categories
wp_set_object_terms($post_id, 'variable', 'product_type'); // Set it to a variable product type
insert_product_attributes($post_id, $product_data['available_attributes'], $product_data['variations']); // Add attributes passing the new post id, attributes & variations
insert_product_variations($post_id, $product_data['variations']); // Insert variations passing the new post id & variations
}
function insert_product_attributes ($post_id, $available_attributes, $variations)
{
foreach ($available_attributes as $attribute) // Go through each attribute
{
$values = array(); // Set up an array to store the current attributes values.
foreach ($variations as $variation) // Loop each variation in the file
{
$attribute_keys = array_keys($variation['attributes']); // Get the keys for the current variations attributes
foreach ($attribute_keys as $key) // Loop through each key
{
if ($key === $attribute) // If this attributes key is the top level attribute add the value to the $values array
{
$values[] = $variation['attributes'][$key];
}
}
}
$values = array_unique($values); // Filter out duplicate values
wp_set_object_terms($post_id, $values, 'pa_' . $attribute);
}
$product_attributes_data = array(); // Setup array to hold our product attributes data
foreach ($available_attributes as $attribute) // Loop round each attribute
{
$product_attributes_data['pa_'.$attribute] = array( // Set this attributes array to a key to using the prefix 'pa'
'name' => 'pa_'.$attribute,
'value' => '',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'
);
}
update_post_meta($post_id, '_product_attributes', $product_attributes_data); // Attach the above array to the new posts meta data key '_product_attributes'
}
function insert_product_variations ($post_id, $variations)
{
foreach ($variations as $index => $variation)
{
$variation_post = array( // Setup the post data for the variation
'post_title' => 'Variation #'.$index.' of '.count($variations).' for product#'. $post_id,
'post_name' => 'product-'.$post_id.'-variation-'.$index,
'post_status' => 'publish',
'post_parent' => $post_id,
'post_type' => 'product_variation',
'guid' => home_url() . '/?product_variation=product-' . $post_id . '-variation-' . $index
);
$variation_post_id = wp_insert_post($variation_post); // Insert the variation
foreach ($variation['attributes'] as $attribute => $value) // Loop through the variations attributes
{
$attribute_term = get_term_by('name', $value, 'pa_'.$attribute); // We need to insert the slug not the name into the variation post meta
update_post_meta($variation_post_id, 'attribute_pa_'.$attribute, $attribute_term->slug);
}
update_post_meta($variation_post_id, '_price', $variation['price']);
update_post_meta($variation_post_id, '_regular_price', $variation['price']);
}
}
function insert_products ($products)
{
if (!empty($products)) // No point proceeding if there are no products
{
array_map('insert_product', $products); // Run 'insert_product' function from above for each product
}
}
$json = file_get_contents('product-data.json'); // Get json from sample file
// $products_data = json_decode($json_file, true); // Decode it into an array
echo json_last_error();
// if(get_magic_quotes_gpc()){
// $d = stripslashes($json);
// }else{
// $d = $json;
// }
$d = json_decode($d,true);
$products_data = json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $json), true );
echo "<h1>json</h1>";
echo "<pre>";
print_r($json);
echo "</pre>";
echo "<h1>Product data</h1>";
echo "<pre>";
var_dump($products_data);
echo "</pre>";
insert_products($products_data);
Where $product_data sample:
$product_data = array(
'sku' => '123SKU',
'categories' => array('size', 'color'),
'available_attributes' => array('size', 'color'),
'variations' => array(
'size' => array(
'attributes' => array( 'XL', 'M', 'S' ),
),
'color' => array(
'attributes' => array( 'Blue', 'Red', 'Green' )
)
)
)
insert_products($products_data);
Note: You can create product-data.json and import product or you can create $product_data = (); and set on insert_products() function.
For Aditional Info:
You can also check this URL for more info https://newbedev.com/create-programmatically-a-woocommerce-product-variation-with-new-attribute-values
i want to apply attribute programmatically in woocommerce, for that i have used this code but it is not working, can anyone please look my code and help me to resolve this issue ?
$product_id = 4931;
$attribute_name = "test_attribute";
$attribute_value = "test_attribute";
$term_taxonomy_ids = wp_set_object_terms($product_id, $attribute_value, $attribute_name, true);
$data = array(
$attribute_name => array(
'name' => $attribute_name,
'value' => '',
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '1'
)
);
//First getting the Post Meta
$_product_attributes = get_post_meta($product_id, '_product_attributes', TRUE);
//Updating the Post Meta
update_post_meta($product_id, '_product_attributes', array_merge($_product_attributes, $data));
}
I recommend to use the wc-functions to handle product data, because in future product data maybe not in wp_post and wp_post_meta table anymore.
$product_id = 4931;
$p = wc_get_product( $product_id );
$my_custom_value = $p->get_meta('_custom_value');
// to change the costum attribute
$p->update_meta_data('_custom_value', $my_new_value );
$p->save();
This links has usefull information:
wc_get_products and WC_Product_Query
Accessing WC_Product protected data in Woocommerce 3
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:
update_post_meta( $post_id, '_product_attributes', array());
However I'm not sure how to properly pass along the attributes and their values?
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!
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.
#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.
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.