WooCommerce - Show custom price in mini cart - php

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

Related

Checkout price different from cart price using woocommerce_product_get_price hook

I´m running a WooCommerce (WordPress 6.1.1 and WooCommerce 7.3.0), and I´m trying to set prices according to the user role.
To do this I have introduced a new field named Webprice (precio_web) in product definition using the plugin: "Advanced Custom Fields". Customer users and not logged users must use this special price.
Also I added this code in my functions.php child-theme:
add_filter('woocommerce_product_get_price', 'ui_custom_price_role', 99, 2);
add_filter('woocommerce_product_get_regular_price', 'ui_custom_price_role', 99, 2);
add_filter('woocommerce_product_variation_get_regular_price', 'ui_custom_price_role', 99, 2);
add_filter('woocommerce_product_variation_get_price', 'ui_custom_price_role', 99, 2);
function ui_custom_price_role($price, $product) {
$price = ui_custom_price_handling($price, $product);
return $price;
}
Variable add_filter('woocommerce_variation_prices_price', 'ui_custom_variable_price', 99, 3);
add_filter('woocommerce_variation_prices_regular_price', 'ui_custom_variable_price', 99, 3);
function ui_custom_variable_price($price, $variation, $product) {
$price = ui_custom_price_handling($price, $product);
return $price;
function ui_custom_price_handling($price, $product) {
//get our current user
$current_user = wp_get_current_user();
//check if the user role is the role we want or is not logged
if ((!is_user_logged_in()) || (isset($current_user - \ > roles\[0\]) && '' != $current_user - \ > roles\[0\] && in_array('customer', $current_user - \ > roles))) { //load the custom price for our product $custom_price = get_post_meta( $product-\>get_id(), 'precio_web', true );
// custom price
if (!empty($custom_price)) {
$price = $custom_price;
}
}
return $price;
}
}
So far It works, when adding items to the cart I can see the new price.
enter image description here
The problem is at checkout for some reason prices displayed are the standard, not the ones corresponding to the new field.
enter image description here
Any help is welcome. Thanks.
I was expecting that the modification of the get_price function was enough because the prices are displayed correctly. However, the order is recorded with the standard price of the item.
WooCommerce recalculates all prices during the checkout process multiple times, so you need to hook into this recalculation also. This should work for you:
add_action( 'woocommerce_before_calculate_totals', 'update_cart_price'), 99);
function update_cart_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$cart_item = $cart_item['data'];
$cart_item_product_id = $cart_item->get_id();
$product = wc_get_product( $cart_item_product_id );
$orig_price = $product->get_regular_price();
$new_price = ui_custom_price_handling( $orig_price, $product );
$cart_item->set_price( $new_price );
}
}

How to hide certain products on WooCommerce cart page

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(..

Problem with woocommerce_add_order_item_meta

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

Set a custom calculated item price in Woocommerce mini-cart / Cart

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

woocommerce_before_calculate_totals fires twice

Writing an addition to the site, want to modify the price in the cart. Have the following code:
function apd_product_custom_price($cart_item_data, $product_id)
{
if (isset($_POST['use_rewards']) && !empty($_POST['use_rewards']))
{
$cart_item_data['use_rewards'] = $_POST['use_rewards'];
}
return $cart_item_data;
}
add_filter('woocommerce_add_cart_item_data', 'apd_product_custom_price', 99, 2);
function apd_apply_custom_price_to_cart_item($cart_object)
{
if( !WC()->session->__isset( 'reload_checkout' )) {
foreach ($cart_object->cart_contents as $value) {
if(isset($value['use_rewards'])) {
$price = $value['data']->get_price() -
$value['use_rewards'];
$value['data']->set_price($price);
}
}
}
}
add_action('woocommerce_before_calculate_totals', 'apd_apply_custom_price_to_cart_item',10);
By some reason the hook woocommerce_before_calculate_totals fires twice. if I replace the code in the function apd_apply_custom_price_to_cart_item($cart_object) with just echo 1; it displays 11 in the cart page. Can some please help?
I forgot the link I should refer to for a solution. You can use this at the top of your function:
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
Most likely some other plugins hooks to 'woocommerce_before_calculate_totals' action.
Try to disable plugins one by one and see witch one is causing this behaviour.
In my case I found that WooCommerce-multilingual plugin hooks to woocommerce_before_calculate_totals action.
So I did this:
add_action( 'woocommerce_before_calculate_totals', '_wm_ponc_upte_prc', 99 );
function _wm_ponc_upte_prc( $cart_object ) {
if ( !WC()->session->__isset( "reload_checkout" ) ) {
foreach ( WC()->cart->get_cart() as $key => $value ) {
// checking if user checked checkbox (optional)
if ( isset( $value['wm_ponc_fee'] ) && ( $value[ 'wm_ponc_fee' ] === 'yes' ) ) {
// your calculations ....
// and Remove your action after you are done.
remove_action( 'woocommerce_before_calculate_totals', '_wm_ponc_upte_prc', 99 );
}
}
}
}
I have removed action after custom calculations. And that's it.
I see exactly the same issue - my hooked function is firing twice, leading to the option price being added at 2x the cost. My solution was to load the product, get the price from that and then add my incremental cost to that.
function tbk_woo_update_option_price( $cart_object ) {
$option_price = 3.50;
foreach ( $cart_object->get_cart() as $cart_item_key => $cart_item ) {
$item_id = $cart_item['data']->id;
//Hook seems to be firing twice for some reason... Get the price from the original product data, not from the cart...
$product = wc_get_product( $item_id );
$original_price = $product->get_price();
$new_price = $original_price + $option_price;
$cart_item['data']->set_price( $new_price );
}
}
add_action( 'woocommerce_before_calculate_totals', 'tbk_woo_update_option_price', 1000, 1 );

Categories