0

I cannot get set_price() to work no matter what I do. To override prices in woocommerce I've noted answers from as recently as 2021 that indicate that you must:

  • Use woocommerce_before_calculate_totals hook instead.
  • Use WC_Cart get_cart() method instead
  • Use WC_product set_price() method instead

Change cart item prices in Woocommerce 3

However, for me, running WC 6.3.1, using the woocommerce_before_calculate_totals hook means it never seems to run at all with any priority from 10 to 9999 (instead of the woocommerce_before_add_to_cart_form hook, which does appear to run).

All of the code snippets I have seen and tried use some version of this loop. If I can get to the function (using woocommerce_before_add_to_cart_form, because woocommerce_before_calculate_totals seems not to run), the $cart object is present, the loop iterates and the get_price() method works.

However, the WC set_price method does not seem to work and the price does not change in the cart. I've seen some note that it works with literal numbers as arguments but not with variables. For me it fails in every form.

I've seen others post this question as well, but I have not seen any recent answers that work. I have also noted some references to session variables being needed to make this work, without explanation of how it would apply to this code.

foreach ( $cart as $cart_item_key => $cart_item ) {

    //Some use $product as the object
    $product = $cart_item['data'];
    $price = $product->get_price();
    $custom_price = $price * 1.1;  
    $product->set_price($custom_price);

    //Some use $cart_item['data'] directly,
    $custom_price = 10;
    $cart_item['data']->set_price($custom_price);

    //Some get fancy with looking for the method
    if( method_exists( $product, 'set_price' ) )
        $product->set_price( $custom_price );
    else
        $product->price = $custom_price;
}
janetbee
  • 1
  • 4
  • It makes no sense to post answers to your question that already exist. It's something that only happens on your specific setup and then it is a matter of debugging – 7uc1f3r Mar 15 '22 at 19:11
  • As I have noted, it is not specific to my setup and other have had the same issue. The answers that have been posted to date are, at best, incomplete in the context of WC 6.3.1. Closing the topic ensures that others with the same issue can not get help finding an answer either, – janetbee Mar 15 '22 at 19:59
  • If you are convinced that this is a bug in WooCommerce (because the problem does not occur for me..), you should report it directly to the developers of WooCommerce – 7uc1f3r Mar 15 '22 at 20:09
  • I am not. I am convinced that the code snippets generally regarded as working are incomplete and are not generally applicable to the current WC environment. As such, a question that prompts a review of the subject is not inappropriate. – janetbee Mar 16 '22 at 00:28

1 Answers1

0

In order to do so I think you need to use one of the WooCommerce hooks and it is working and tested.

add_action( 'woocommerce_before_calculate_totals', 'function_name_here', 1000, 1);

function function_name_here($cart){
//You can then use set_price() here

foreach ( $cart as $cart_item_key => $cart_item ) {

    //Some use $product as the object
    $product = $cart_item['data'];
    $price = $product->get_price();
    $custom_price = $price * 1.1;  
    $product->set_price($custom_price);

    //Some use $cart_item['data'] directly,
    $custom_price = 10;
    $cart_item['data']->set_price($custom_price);

    //Some get fancy with looking for the method
    if( method_exists( $product, 'set_price' ) )
        $product->set_price( $custom_price );
    else
        $product->price = $custom_price;
}
}

Thanks!


New Edit:

This is the version I have tested and it appears to be working great, Tested on Storefront theme.

I have just tested this block of code, It is working good here!

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;

    foreach ( $cart->get_cart() as $cart_item ) {
        $cart_item['data']->set_price( 40 );
    }
}
Ara PHP
  • 87
  • 6
  • Thanks - I've used that hook and created a similar function. Two issues - first is that the WooCommerce_before_calculate_totals hook doesn't seem to run. Second, however you hook to it, the set_price method doesn't work. – janetbee Mar 15 '22 at 17:25
  • It depends on where did you add the hook and the callback function, If you add them to your current theme functions.php, I believe it will work 100% as long as nothing else uses the same hook or prevent it from firing. – Ara PHP Mar 15 '22 at 17:28
  • I have a child theme setup with a variety of well working functions called by various actions. As mentioned, I've tried priorities from 10 to 9999 and see nothing from that hook. The woocommerce_before_add_to_cart_form hook fires and I can still get the cart object, but the set_price method doesn't work. As I indicated, I don't think we have any reason to think these code snippets for this type of price override work. More than a few say they don't and there are no recent answers to this question. There have been some suggestions that a session variable is needed to make this code work. – janetbee Mar 15 '22 at 17:33
  • I have edited the answer with the working version, I tested it, You can modify the code the way you want. – Ara PHP Mar 15 '22 at 17:51
  • I have tried exactly that code previously and just re-confirmed that it does not work for me, using Avada. Others with a similar problem have noted that a session variable needs to be set before calling the function, but I'm not clear on how that would happen: https://stackoverflow.com/questions/65108993/woocommerce-set-price-function-inconsistency?rq=1 – janetbee Mar 15 '22 at 17:59
  • If you do a var_dump($cart_item); You can get the cart key which may be the session variable you need, It displays something like: array(12) { ["key"]=> string(32) "502e4a16930e414107ee22b6198c578f" ["product_id"]=> int(258) ["variation_id"]=> int(0) ["variation"]=> array(0) { } – Ara PHP Mar 15 '22 at 18:05
  • I don't think that was the sense of it. This was referring to explicitly setting and retrieving session variables: https://wordpress.org/support/topic/trying-to-change-cart-pricing/ - Loic has said something similar here in my comment above. That much said, there is another way of looping through the foreach that uses the key: foreach ( $cart_object->get_cart() as $cart_item_key => $cart_item ) - it doesn't work either ;) – janetbee Mar 15 '22 at 18:11
  • I already tested the code I pasted and it worked without any edits that could relate to the cart sessions ... etc, That's why I am wondering why you have such issue, But you may need to ensure that the hook is called properly, You can print anything in the hook and check the (Network) tab in the developers tool panel to see whether it says anything or not, May be this is the real issue. – Ara PHP Mar 15 '22 at 18:15
  • There isn't much to "calling the hook properly" ;) I don't think it is any more complicated than below. As noted, I have tried lots of priorities as well. `add_action( 'woocommerce_before_calculate_totals', 'custom_price_cart_upate', 1000, 1 );` – janetbee Mar 15 '22 at 18:20
  • Anticipating suggestions that the theme could be a culprit, I also tested it with a child theme of TwentyTwenty with the same result. – janetbee Mar 15 '22 at 18:35