4

In Woocommerce, I used jQuery to calculate a custom price on a single product pages, and now need to pass this value to the cart.

The desired behavior is to pass the new price retrieved from the hidden field to the cart item price.

Here is my actual code:

// Hidden input field in single product page
add_action( 'woocommerce_before_add_to_cart_button', 'custom_hidden_product_field', 11, 0 );
function custom_hidden_product_field() {
    echo '<input type="hidden" id="hidden_field" name="custom_price" class="custom_price" value="">';
}


// The code to pass this data to the cart:
add_action( 'woocommerce_add_cart_item_data', 'save_custom_fields_data_to_cart', 10, 2 );
function save_custom_fields_data_to_cart( $cart_item_data, $product_id ) {

    if( ! empty( $_REQUEST['custom_price'] ) ) {
        // Set the custom data in the cart item
        $cart_item_data['custom_data']['custom_price'] = $_REQUEST['custom_price'];
        $data = array( 'custom_price' => $_REQUEST['custom_price'] );
        
        // below statement make sure every add to cart action as unique line item
        $cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
        WC()->session->set( 'custom_data', $data );
    }
    return $cart_item_data;
}

And check both $data and $cart_item_data to see that they both return the custom_price data that is calculated on the page.

However, I go to view cart, and the value of the line item is still 0.

I set a var equal to the WC()->session->set( 'custom_data', $data ); and then var_dump to check it, but this returns NULL which might just be what it returns, I'm not entirely sure because I've never used it.

I should also add that I have the regular_price in the product backend set to 0. When I erase this (and leave it blank) I get back the error:

Warning: A non-numeric value encountered in C:\xampp\htdocs\my-transfer-source\wp-content\plugins\woocommerce\includes\class-wc-discounts.php on line 85

I'm wondering if I've missed something here, and if someone could lend some light onto this? Thanks

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
logos_164
  • 736
  • 1
  • 13
  • 31
  • Hi thanks for responding, but besides my hidden field, that is my complete code, so I'm not sure what other code you want. – logos_164 Sep 12 '18 at 22:23
  • The desired behavior is to pass the new price retrieved from the hidden field to the Woocommerce cart price. Does that make sense? I'll add that to the question. – logos_164 Sep 12 '18 at 22:24

1 Answers1

7

Update 2021 - Handling custom price item in mini cart

First for testing purpose we add a price in the hidden input field as you don't give the code that calculate the price:

// Add a hidden input field (With a value of 20 for testing purpose)
add_action( 'woocommerce_before_add_to_cart_button', 'custom_hidden_product_field', 11 );
function custom_hidden_product_field() {
    echo '<input type="hidden" id="hidden_field" name="custom_price" class="custom_price" value="20">'; // Price is 20 for testing
}

Then you will use the following to change the cart item price (WC_Session is not needed):

// Save custom calculated price as custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_fields_data_to_cart', 10, 2 );
function save_custom_fields_data_to_cart( $cart_item_data, $product_id ) {

    if( isset( $_POST['custom_price'] ) && ! empty( $_POST['custom_price'] )  ) {
        // Set the custom data in the cart item
        $cart_item_data['custom_price'] = (float) sanitize_text_field( $_POST['custom_price'] );

        // Make each item as a unique separated cart item
        $cart_item_data['unique_key'] = md5( microtime().rand() );
    }
    return $cart_item_data;
}

// For mini cart
add_action( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 2 );
function filter_cart_item_price( $price, $cart_item ) {
    if ( isset($cart_item['custom_price']) ) {
        $args = array( 'price' => floatval( $cart_item['custom_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;
}

// Updating cart item price
add_action( 'woocommerce_before_calculate_totals', 'change_cart_item_price', 30, 1 );
function change_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 ) {
        // Set the new price
        if( isset($cart_item['custom_price']) ){
            $cart_item['data']->set_price($cart_item['custom_price']);
        }
    }
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • That did it. Why isn't setting WC()->session necessary? – logos_164 Sep 12 '18 at 22:45
  • 1
    I have made a light update… WC_Session data is not needed as we have the necessary data as custom cart item data… if you try: `print_r($cart_item);` inside the cart items foreach loop, you will see what I mean. – LoicTheAztec Sep 12 '18 at 22:49
  • 1
    @logos_164 You see nearly the same thing in [this very recent answer](https://stackoverflow.com/a/52297101/3730754)… WC_Session is not used too. WC_session is mostly used when you need to set a value outside cart items, to be able to get it on Ajax powered code, for example. Woocommerce use WC_Session to store the customer chosen options, for example. – LoicTheAztec Sep 12 '18 at 23:01
  • This example at the above on your comment , change pricees automaticly. İ want to change price with text input field, on the loap and cart page. İs it possible . Thx – musa baltaci Mar 29 '21 at 10:59
  • 1
    @musabaltaci You can use something like https://stackoverflow.com/a/48128915/3730754 making some changes, where you will replace the hidden input field with a text input field… Try something yourself and ask a new question if you need help… – LoicTheAztec Mar 29 '21 at 11:12
  • Ok i will try. Thx – musa baltaci Mar 29 '21 at 12:22