i have spent the last 3 hours trying to fix a problem with a woocommerce deprecated hook and i'm going crazy because i have tried hundred different options to make it work, and it's not happening.
This is the actual code, it suppose to save the value of custom fields. Any idea about how to make it work with a non obsolete hook?
add_action('woocommerce_add_order_item_meta','save_in_order_item_meta', 10, 3 );
function save_in_order_item_meta( $item_id, $values, $cart_item_key ) {
if( isset( $values['custom_data'] ) ) {
woocommerce_new_order_item( $item_id, $values['custom_data']['label'], $values['custom_data']['value'] );
}
}
Any help is welcome. Thank you
Edit;
Already tried.
add_action( 'woocommerce_add_order_item_meta', 'custom_add_order_item_meta', 20, 3 ); function custom_add_order_item_meta(
$item_id, $values, $cart_item_key ) { // Get cart item custom data and update order item meta if( isset( $values['custom_data'] ) ) {
wc_add_order_item_meta( $item_id, $values['custom_data']['label'], $values['custom_data']['value'] ); } }
add_action( 'woocommerce_add_order_item_meta', 'custom_add_order_item_meta', 20, 3 );
function custom_add_order_item_meta( $item_id, $values, $cart_item_key ) {
$custom_field_value = $custom_field_value;
if ( ! empty( $custom_field_value ) ){
wc_add_order_item_meta( $item_id, $values['custom_data']['label'], $values['custom_data']['value'] );
}
}
Hook woocommerce_add_order_item_meta is replaced by woocommerce_checkout_create_order_line_item, so with your code (assuming that the cart object contains your custom cart item data):
add_action('woocommerce_checkout_create_order_line_item', 'save_custom_order_item_meta_data', 10, 4 );
function save_custom_order_item_meta_data( $item, $cart_item_key, $values, $order ) {
if( isset( $values['custom_data']['label'] ) && isset( $values['custom_data']['value'] ) ) {
$item->update_meta_data( $values['custom_data']['label'], $values['custom_data']['value'] );
}
}
Code goes in function.php file of your active child theme (or active theme). It should works.
Related:
Replace woocommerce_add_order_item_meta hook in Woocommerce 3.4
Woocommerce: Which hook to replace deprecated "woocommerce_add_order_item_meta"
Threads with: woocommerce_checkout_create_order_line_item action hook
Related
I have changed the main WooCommerce cart page using CSS to hide the products on this page.
The reason for the change, I am attempting to dedicate the cart page to only show the product "Thank You For The Tip" if it is in the cart, without changing any of the WooCommerce product settings to hidden.
All other products that have been added to the cart need to be hidden on the main WooCommerce cart page.
I see that I can not achieve this with CSS as the changes I made to the CSS will hide all products that have been added to the cart.
The closest I have come to finding a PHP solution is the following snippet:
add_filter( 'woocommerce_cart_item_visible', 'bbloomer_hide_hidden_product_from_cart' , 10, 3 );
add_filter( 'woocommerce_widget_cart_item_visible', 'bbloomer_hide_hidden_product_from_cart', 10, 3 );
add_filter( 'woocommerce_checkout_cart_item_visible', 'bbloomer_hide_hidden_product_from_cart', 10, 3 );
add_filter( 'woocommerce_order_item_visible', 'bbloomer_hide_hidden_product_from_order_woo333', 10, 2 );
function bbloomer_hide_hidden_product_from_cart( $visible, $cart_item, $cart_item_key ) {
$product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
if ( $product->get_catalog_visibility() == 'hidden' ) {
$visible = false;
}
return $visible;
}
function bbloomer_hide_hidden_product_from_order_woo333( $visible, $order_item ) {
$product = $order_item->get_product();
if ( $product->get_catalog_visibility() == 'hidden' ) {
$visible = false;
}
return $visible;
}
However, this does not give the desired result. Any advice?
To hide certain WooCommerce products only on the cart page and nowhere else, it suffices to just use the woocommerce_cart_item_visible filter hook.
In the $targeted_ids array you can indicate which productIDs should remain visible. This also works for variationIDs
function filter_woocommerce_cart_item_visible( $true, $cart_item, $cart_item_key ) {
// The targeted product ids
$targeted_ids = array( 30, 53 );
// Computes the intersection of arrays
if ( ! array_intersect( $targeted_ids, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
$true = false;
}
return $true;
}
add_filter( 'woocommerce_cart_item_visible', 'filter_woocommerce_cart_item_visible', 10, 3 );
To apply the reverse, and hide the productIDs that occur in the array
Replace
if ( ! array_intersect(..
With
if ( array_intersect(..
I know how to add a meta on the order shipping method :
$shippingMethodItem->update_meta_data('num_packages', 0);
But I want to add/update this meta automatically when the order is placed OR when someone add/edit order items manually.
I already tried with no result :
add_action( 'woocommerce_checkout_create_order_shipping_item', [$this, 'actionCheckoutCreateOrderShippingItem'] );
...
public function actionCheckoutCreateOrderShippingItem ($shippingMethodItem, $package_key, $package, $order)
{
$shippingMethodItem->update_meta_data( 'num_packages', 0);
$shippingMethodItem->save();
}
The following will add custom specific order "shipping" item meta data on orders via checkout and/or manual admin orders too:
// For new orders via checkout
add_action( 'woocommerce_checkout_create_order_shipping_item', 'action_checkout_create_order_shipping_item', 10, 4 );
function action_checkout_create_order_shipping_item ( $item, $package_key, $package, $order ){
$item->update_meta_data( 'num_packages', 0 );
}
// For manual admin orders
add_action( 'woocommerce_saved_order_items', 'action_saved_order_items_callback', 10, 2 );
function action_saved_order_items_callback( $order_id, $items ) {
if ( isset( $items['shipping_method_id'] ) ) {
foreach( $items['shipping_method_id'] as $item_id ) {
$num_packages = wc_get_order_item_meta($item_id, 'num_packages');
if ( empty($num_packages) || $num_packages != 0 ) {
wc_update_order_item_meta( $item_id, 'num_packages', 0 );
}
}
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
To use this code in a plugin with a class (OOP), add the following inside the constructor function:
// For checkout order
add_action( 'woocommerce_checkout_create_order_shipping_item', [$this, 'action_checkout_create_order_shipping_item'], 10, 4 );
// For checkout order
add_action( 'woocommerce_saved_order_items', [$this, 'action_saved_order_items_callback'], 10, 2 );
And the following outside the constructor function:
public function action_checkout_create_order_shipping_item ( $item, $package_key, $package, $order ){
$item->update_meta_data( 'num_packages', 0 );
}
public function action_saved_order_items_callback( $order_id, $items ) {
if ( isset( $items['shipping_method_id'] ) ) {
foreach( $items['shipping_method_id'] as $item_id ) {
$num_packages = wc_get_order_item_meta($item_id, 'num_packages');
if ( empty($num_packages) || $num_packages != 0 ) {
wc_update_order_item_meta( $item_id, 'num_packages', 0 );
}
}
}
}
I'm using the following code for dynamic pricing on WooCommerce products:
function add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
if( ! empty( $_POST['custom-total-price'] ) ) {
$product = wc_get_product( $product_id );
$price = $product->get_price();
$cart_item_data['custom_price'] = $_POST['custom-total-price'];
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_data', 10, 3 );
function before_calculate_totals( $cart_obj ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
foreach( $cart_obj->get_cart() as $key=>$value ) {
if( isset( $value['custom_price'] ) ) {
$price = $value['custom_price'];
$value['data']->set_price( ( $price ) );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'before_calculate_totals', 10, 1 );
The price is calculated with jQuery on the front end and sent through a form input when the product is added to the cart.
This is working in the sense that the cart total is updated, and the custom price for individual items is shown on the cart page. However, it's still showing a price of 0 in the mini cart. Any idea how I can show the custom price in the mini cart?
add_filter( 'woocommerce_cart_item_price', 'woocommerce_cart_item_price_filter', 10, 3 );
function woocommerce_cart_item_price_filter( $price, $cart_item, $cart_item_key ) {
/*
calculate price
*/
return $yourPrice;
}
I hope this helps you
In wooCommerce plugin I want to send $item['_custom_sizer'] this value to check out page and email template but i am not able to pass the value. please help me out.
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_custom_data_vase', 10, 2 );
function add_cart_item_custom_data_vase( $cart_item_meta, $product_id ) {
global $woocommerce;
$new_value = array();
$new_value['_custom_sizer'] = $_POST['sizer'];
if(empty($cart_item_data)) {
return $new_value;
} else {
return array_merge($cart_item_data, $new_value);
}
}
//Get it from the session and add it to the cart variable
function get_cart_items_from_session( $item, $values, $key ) {
if (array_key_exists( '_custom_sizer', $values ) ) {
$item['_custom_sizer'] = $values['_custom_sizer'];
}
return $item;
}
add_filter( 'woocommerce_get_cart_item_from_session', 'get_cart_items_from_session', 1, 3 );
Updated… Try the following instead:
// Add "Sizer" as custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_custom_data', 20, 2 );
function add_cart_item_custom_data( $cart_item_data, $product_id ) {
if( isset($_POST['sizer']) && ! empty($_POST['sizer']) ){
$cart_item_data['custom_sizer'] = sanitize_text_field( $_POST['sizer'] );
}
return $cart_item_data;
}
// Display "Sizer" in cart and checkout
add_filter( 'woocommerce_get_item_data', 'display_sizer_in_cart_checkout', 20, 2 );
function display_sizer_in_cart_checkout( $cart_item_data, $cart_item ) {
if( isset($cart_item['custom_sizer']) ){
$cart_item_data[] = array(
'name' => __('Metal Type'),
'value' => $cart_item['custom_sizer'],
);
}
return $cart_item_data;
}
// Save "sizer" as custom order item meta data
add_action( 'woocommerce_checkout_create_order_line_item', 'update_order_item_meta', 20, 4 );
function update_order_item_meta( $item, $cart_item_key, $values, $order ) {
if( isset($values['custom_sizer']) )
$item->update_meta_data( 'Sizer', $values['custom_sizer'] );
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Currently i have some custom calculation of product price based on different situation. When customer added a product in to cart then the custom price is set in session data , cart_item_data['my-price'] and i implemented using add_filter( 'woocommerce_add_cart_item') function and everything seems to working now .
Now the price in view cart page, checkout page is correct with my cart_item_data['my-price'].
But the only problem i am facing is the price is not updated in woocommerce mini cart that is appeared in the menu ,How can i change this ?
When i google i see a filter
add_filter('woocommerce_cart_item_price');
but i can't understand how to use this i do the following
add_filter('woocommerce_cart_item_price','modify_cart_product_price',10,3);
function modify_cart_product_price( $price, $cart_item, $cart_item_key){
if($cart_item['my-price']!==0){
$price =$cart_item['my-price'];
}
return $price;
//exit;
}
Here individual price is getting correct , but total price is wrong
Updated (october 2021)
For testing this successfully (and as I don't know how you make calculations), I have added a custom hidden field in product add to cart form with the following:
// The hidden product custom field
add_action( 'woocommerce_before_add_to_cart_button', 'add_gift_wrap_field' );
function add_gift_wrap_field() {
global $product;
// The fake calculated price
?>
<input type="hidden" id="my-price" name="my-price" value="115">
<?php
}
When product is added to cart, this my-price custom field is also submitted (posted). To set this value in cart object I use the following function:
add_filter( 'woocommerce_add_cart_item', 'custom_cart_item_prices', 20, 2 );
function custom_cart_item_prices( $cart_item_data, $cart_item_key ) {
// Get and set your price calculation
if( isset( $_POST['my-price'] ) ){
$cart_item_data['my-price'] = $_POST['my-price'];
// Every add to cart action is set as a unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
}
return $cart_item_data;
}
Now to apply (set) the new calculated price my-price to the cart item, I use this last function:
// For mini cart *(cart item displayed price)*
add_action( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 2 );
function filter_cart_item_price( $price, $cart_item ) {
if ( ! is_checkout() && isset($cart_item['my-price']) ) {
$args = array( 'price' => floatval( $cart_item['my-price'] ) );
if ( WC()->cart->display_prices_including_tax() ) {
$product_price = wc_get_price_including_tax( $cart_item['data'], $args );
} else {
$product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
}
return wc_price( $product_price );
}
return $price;
}
add_action( 'woocommerce_before_calculate_totals', 'set_calculated_cart_item_price', 20, 1 );
function set_calculated_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ){
if( isset( $cart_item['my-price'] ) && ! empty( $cart_item['my-price'] ) || $cart_item['my-price'] != 0 ){
// Set the calculated item price (if there is one)
$cart_item['data']->set_price( $cart_item['my-price'] );
}
}
}
All code goes in function.php file of your active child theme (or active theme).
Tested and works