woocommerce product attribute not working programmatically - wordpress

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

Related

WooCommerce to update newest group of attributes

I need to programmatically update a product attributes with the current value and found a very useful answer to do just that. However, it seems that in order for the attributes to be added, the terms must be defined first. So I added a wp_insert_term function to add new the terms before updating the attributes. The code works great but it keep appending the new attributes whereas it should only have newest value only. Please advice me if you have a solution.
$product_id = 11874;
$attributes_data = array(
array('name'=>'Size', 'options'=>array('S', 'L', 'XL', 'XXL'), 'visible' => 1, 'variation' => 1 ),
array('name'=>'Color', 'options'=>array('Red', 'Blue', 'Black', 'White'), 'visible' => 1, 'variation' => 1 )
);
if( sizeof($attributes_data) > 0 ){
$attributes = array(); // Initializing
// Loop through defined attribute data
foreach( $attributes_data as $key => $attribute_array ) {
if( isset($attribute_array['name']) && isset($attribute_array['options']) ){
// Clean attribute name to get the taxonomy
$taxonomy = 'pa_' . wc_sanitize_taxonomy_name( $attribute_array['name'] );
$option_term_ids = array(); // Initializing
// Loop through defined attribute data options (terms values)
foreach( $attribute_array['options'] as $option ){
if( !term_exists( $option, $taxonomy ) ){
wp_insert_term($option, $taxonomy);
}
// Save the possible option value for the attribute which will be used for variation later
wp_set_object_terms( $product_id, $option, $taxonomy, true );
// Get the term ID
$option_term_ids[] = get_term_by( 'name', $option, $taxonomy )->term_id;
}
}
// Loop through defined attribute data
$attributes[$taxonomy] = array(
'name' => $taxonomy,
'value' => $option_term_ids, // Need to be term IDs
'position' => $key + 1,
'is_visible' => $attribute_array['visible'],
'is_variation' => $attribute_array['variation'],
'is_taxonomy' => '1'
);
}
// Save the meta entry for product attributes
update_post_meta( $product_id, '_product_attributes', $attributes );
}

How to programmatically set the product attribute variation price in woocommerce?

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

Woocommerce not saving form field

i cannot figure out what i am missing.
I created a custom textfield at the woocommerce checkout with a predefined value. Function is pretty standard:
function one_more_field(){
$product_name='';
global $product;
foreach( WC()->cart->get_cart() as $cart_item ){
$productvariation = $cart_item['variation_id'];
}
woocommerce_form_field( 'variatie', array(
'type' => 'text',
'value' => $productvariation,
),
$productvariation );
}
add_action( 'woocommerce_after_checkout_billing_form', 'one_more_field' );
I can see the field in the checkout and the variation ID is nicely inserted.
Then step 2: saving the value to the user meta data:
function reigel_woocommerce_checkout_update_user_meta( $customer_id, $posted ) {
$dob4 = 'test';
if (isset($posted['variatie'])) {
$dob4 = $posted['variatie'];
update_user_meta( $customer_id, 'variatie', $dob4);
}
add_action( 'woocommerce_checkout_update_user_meta', 'reigel_woocommerce_checkout_update_user_meta', 10, 2 );
However, the value is not saved to the user meta data.
What am i missing here?
Oh it turns out to be very straightforward: just add required => yes to the array of field arguments and it is saved. Cant really understand why though...
So new code (step 1) is:
function one_more_field(){
$product_name='';
global $product;
foreach( WC()->cart->get_cart() as $cart_item ){
$productvariation = $cart_item['variation_id'];
}
woocommerce_form_field( 'variatie', array(
'type' => 'text',
'value' => $productvariation,
'required' => 'true'
),
$productvariation );
}
add_action( 'woocommerce_after_checkout_billing_form', 'one_more_field' );

How update product attributes programmatically?

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

Get slug from a woocommerce product using a product id

I want to get the slug of each product in a woocommerce order/purchase of current user.
Steps i took
1.I fetched current user's order.
2.Then I get items/products from the order
$args = array(
'customer_id' => $user->ID
'status' => 'completed'
);
//getting the orders
$orders = wc_get_orders($args);
$orderInfo = [
'id' => [],
'name' => [],
'slug' => []
];
foreach($orders as $order){
foreach( $order->get_items() as $item_id => $item ){
array_push( $orderInfo['id'], $item->get_product_id() );
array_push( $orderInfo['name'], $item->get_name() );
array_push( $orderInfo['slug'], $item->get_slug() );
}
}
After fetching products i am able to get product id and name. But when using $item->get_slug, I am facing this error.
Fatal error: Uncaught Error: Call to undefined method
WC_Order_Item_Product::get_slug()
What wrong am i doing?
You should try this
$product = get_post( $item->get_product_id() );
$slug = $product->post_name;
array_push( $orderInfo['slug'], $slug );

Resources