Change WooCommerce cart item price based on a custom field and quantity threshold
In your code $variation_data['variation_id']
is not defined as $variation_data
doesn't exist for woocommerce_before_calculate_totals
hook… Try the following instead:
add_action( 'woocommerce_before_calculate_totals', 'quantity_based_bulk_pricing', 9999, 1 );
function quantity_based_bulk_pricing( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Define the quantity threshold
$qty_threshold = 6;
// Loop through cart items
foreach( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Get the bulk price from product (variation) custom field
$bulk_price = (float) $cart_item['data']->get_meta('bulk_price');
// Check if item quantity has reached the defined threshold
if( $cart_item['quantity'] >= $qty_threshold && $bulk_price > 0 ) {
// Set the bulk price
$cart_item['data']->set_price( $bulk_price );
}
}
}
Code goes in functions.php file of your active child theme (or active theme). It should works.
Change cart item prices based on custom cart item data in Woocommerce
You need to use 2 different hooks:
- The first one just as yours without trying to change the price in it.
- The second one where you will change your cart item price
The code:
add_filter( 'woocommerce_add_cart_item', 'add_custom_cart_item_data', 10, 2 );
function add_custom_cart_item_data( $cart_item_data, $cart_item ) {
if( isset( $_POST['new-width'] ) )
$cart_item_data['new-width'] = $_POST['new-width'];
if(isset( $_POST['new-height'] ) )
$cart_item_data['new-height'] = $_POST['new-height'];
return $cart_item_data;
}
add_action( 'woocommerce_before_calculate_totals', 'set_custom_cart_item_price', 20, 1 );
function set_custom_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// First loop to check if product 11 is in cart
foreach ( $cart->get_cart() as $cart_item ){
if( isset($cart_item['new-width']) && isset($cart_item['new-height'])
&& ! empty($cart_item['new-width']) && ! empty($cart_item['new-height']) )
$cart_item['data']->set_price( '30' );
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works
Issue with changing WooCommerce cart item prices based on product meta
The woocommerce_cart_item_name
hook is being misused in your code attempt. A filter hook should always return something compared to the use of echo.
You should use the woocommerce_before_calculate_totals
hook instead
So you get:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Change price if > 3000
$threshold = 3000;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get regular price
$price = $cart_item['data']->get_regular_price();
// Subtotal = Get quantity * price
$subtotal = $cart_item['quantity'] * $price;
// Greater than
if ( $subtotal > $threshold ) {
// Get meta
$meta = $cart_item['data']->get_meta( '_opt_price_var', true );
// NOT empty
if ( ! empty ( $meta ) ) {
// Set new price
$cart_item['data']->set_price( $meta );
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
Increase cart item prices based on payment method in WooCommerce
There are some mistakes in your code
- Use
WC()->session->get( 'chosen_payment_method' );
outside the foreach loop get_post_meta()
is not needed to get the price, you can useget_price()
- You will also need jQuery that is triggered when changing the payment method.
So you get:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Get payment method
$chosen_payment_method = WC()->session->get( 'chosen_payment_method' );
// Compare
if ( $chosen_payment_method == 'cod' ) {
$increaseby = 3;
} elseif ( $chosen_payment_method == 'paypal' ) {
$increaseby = 8;
} else {
$increaseby = 10;
}
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Get price
$price = $cart_item['data']->get_price();
// Set price
$cart_item['data']->set_price( $price + ( $price * $increaseby ) / 100 );
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
function action_wp_footer() {
if ( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script type="text/javascript">
jQuery(function($){
$( 'form.checkout' ).on( 'change', 'input[name="payment_method"]', function() {
$(document.body).trigger( 'update_checkout' );
});
});
</script>
<?php
endif;
}
add_action( 'wp_footer', 'action_wp_footer' );
Change cart item prices in Woocommerce 3
Update 2021 (Handling mini cart custom item price)
With WooCommerce version 3.0+ you need:
- To use
woocommerce_before_calculate_totals
hook instead. - To use WC_Cart
get_cart()
method instead - To use WC_product
set_price()
method instead
Here is the code:
// Set custom cart item price
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);
function add_custom_price( $cart ) {
// This is necessary for WC 3.0+
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Avoiding hook repetition (when using price calculations for example | optional)
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
$cart_item['data']->set_price( 40 );
}
}
And for mini cart (update):
// Mini cart: Display custom price
add_filter( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 3 );
function filter_cart_item_price( $price_html, $cart_item, $cart_item_key ) {
if( isset( $cart_item['custom_price'] ) ) {
$args = array( 'price' => 40 );
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_html;
}
Code goes in functions.php file of your active child theme (or active theme).
This code is tested and works (still works on WooCommerce 5.1.x).
Note: you can increase the hook priority from
20
to1000
(or even2000
) when using some few specific plugins or others customizations.
Related:
- Set cart item price from a hidden input field custom price in Woocommerce 3
- Change cart item prices based on custom cart item data in Woocommerce
- Set a specific product price conditionally on Woocommerce single product page & cart
- Add a select field that will change price in Woocommerce simple products
How to set custom product price after add to cart in WooCommerce?
You used woocommerce_add_cart_item_data
to add custom meta is right but you didn't set custom price to product price.
function wdm_add_item_data( $cart_item_data, $product_id ) {
$cart_item_data[ "_custom_options" ] = 678
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'wdm_add_item_data', 10, 2 );
Use the
woocommerce_before_calculate_totals
action hook to set
custom price to product in the cart.
function woocommerce_custom_price_to_cart_item( $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
if( isset( $value["_custom_options"] ) ) {
$value['data']->set_price($value["_custom_options"]);
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'woocommerce_custom_price_to_cart_item', 10 );
Customize cart item subtotal based on custom cart item data in Woocommerce
You are not doing that in the right way and you need to rethink it differently…
Here is a complete example that will allow you to keep the default item price (product price) and to get a calculated cart item subtotal based on your "length" custom cart item data:
// For testing (example): Add a dropdown to product page for lenght
add_action( 'woocommerce_before_add_to_cart_button', 'add_lenght_custom_field');
function add_lenght_custom_field() {
echo '<div class="class_dropdown_length">
<label for="rope_length">Select a length</label>
<select id ="rope_length" name="rope_length">
<option value="">1 m</option>
<option value="5">5 m</option>
<option value="10">10 m</option>
<option value="25">25 m</option>
</select>
</div>';
}
// Add custom cart item data (lenght) on add to cart and calculate the new price
add_filter( 'woocommerce_add_cart_item_data', 'filter_woocommerce_add_cart_item_data', 10, 3 );
function filter_woocommerce_add_cart_item_data( $cart_item_data, $product_id, $variation_id) {
if( isset($_POST['rope_length']) && ! empty($_POST['rope_length']) ) {
$the_id = $variation_id > 0 ? $variation_id : $product_id;
$product = wc_get_product( $the_id );
$length = (float) esc_attr($_POST['rope_length']); // The chosen lenght
// Add the dropdown value as custom cart item data
$cart_item_data['custom'] = array(
'length' => $length, // The lenght value from custom field (if needed)
'price' => $product->get_price(), // The default product price
'new_price' => $product->get_price() * $length, // Calculated price from lenght
'unique_key' => md5(microtime().rand()), // Make each item unique
);
}
return $cart_item_data;
}
// Display the selected lenght value below cart item name
add_filter( 'woocommerce_cart_item_name', 'display_select_length_after_cart_item_name', 10, 3 );
function display_select_length_after_cart_item_name( $name, $cart_item, $cart_item_key ) {
if( is_cart() && isset($cart_item['custom']['length']) ) {
$name .= '<p>'.__("Lenght:") . ' ' . esc_html($cart_item['custom']['length']) . '</p>';
}
return $name;
}
// Display the default product price (instead of the calculated one)
add_filter( 'woocommerce_cart_item_price', 'filter_woocommerce_cart_item_price', 10, 3 );
function filter_woocommerce_cart_item_price( $product_price, $cart_item, $cart_item_key ) {
if( isset($cart_item['custom']['price']) ) {
$product_price = wc_price( wc_get_price_to_display( $cart_item['data'], array('price' => $cart_item['custom']['price']) ) );
}
return $product_price;
}
// Customizing cart item price subtotal
add_action( 'woocommerce_before_calculate_totals', 'set_cart_item_calculated_price', 10, 1 );
function set_cart_item_calculated_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Required since Woocommerce version 3.2 for cart items properties changes
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Set the new calculated price based on lenght
if( isset($cart_item['custom']['new_price']) ) {
$cart_item['data']->set_price( $cart_item['custom']['new_price'] );
}
}
}
This code goes in function.php file of your active child theme (or active theme). Tested and works.
You can see that the product price is different that the custom calculated subtotal (price x length):
Display and save added custom cart item data on Woocommerce Cart, Checkout and Orders
To display and save custom meta data added to cart in cart, checkout and orders when using:
WC()->cart->add_to_cart( $product_id ,1, 0,array(), array('add_size' => array('PR CODE'=>'1.0') );
You will use the following code:
// Display custom cart item meta data (in cart and checkout)
add_filter( 'woocommerce_get_item_data', 'display_cart_item_custom_meta_data', 10, 2 );
function display_cart_item_custom_meta_data( $item_data, $cart_item ) {
$meta_key = 'PR CODE';
if ( isset($cart_item['add_size']) && isset($cart_item['add_size'][$meta_key]) ) {
$item_data[] = array(
'key' => $meta_key,
'value' => $cart_item['add_size'][$meta_key],
);
}
return $item_data;
}
// Save cart item custom meta as order item meta data and display it everywhere on orders and email notifications.
add_action( 'woocommerce_checkout_create_order_line_item', 'save_cart_item_custom_meta_as_order_item_meta', 10, 4 );
function save_cart_item_custom_meta_as_order_item_meta( $item, $cart_item_key, $values, $order ) {
$meta_key = 'PR CODE';
if ( isset($values['add_size']) && isset($values['add_size'][$meta_key]) ) {
$item->update_meta_data( $meta_key, $values['add_size'][$meta_key] );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Example display on Cart (and Checkout) pages:
Example display on Orders (and email notifications):
Related Topics
Url Querystring with a PHP Include
I Want a Pagination to My Options Page of Wordpress Plugin
Call to Undefined Function Password_Hash()
Codeigniter PHP Stylesheet Link. How
Echo PHP Variable from JavaScript
How to Join Three Tables in Codeigniter
Regular Expressions: How to Express \W Without Underscore
Laravel Collection Converts Array to Object
How to 'JSON_Encode()' Keys from PHP Array
Using Mod_Rewrite with Xampp and Windows 7 - 64 Bit
How to Make First Letter of a Word Capital
Notice: Undefined Index: Http_Referer
Move the Variation Price Location in Woocommerce