Trying to change cart pricing
-
Hi. I want to change cart item pricing but (I’m guessing this is due to AJAX handling?) I cannot seem to be able to use the action “woocommerce_before_calculate_totals” to iterate through the cart items to find the product whose price I’d like to adjust, and then set_price() on the line item with the new price.
I have constants defined with the special sale price (‘FITSALEPRICE’) and product id (‘FITPID’). Here’s what I’m trying to do, but this does not seem to work with the sidecart:
add_action( 'woocommerce_before_calculate_totals', 'pricecartvariations', 99 ); function pricecartvariations( $cart ) { if (defined('FITSALEPRICE') && defined('FITPID')) { foreach ($cart->get_cart() as $key=>$value) { if ( $value['product_id'] == FITPID ) { $value['data']->set_price(FITSALEPRICE); } } } }
It seems like this action never gets called, so when WC Side Cart writes $product_price with WC->cart->get_product_price() only the original price shows in the cart – not the special sale price defined by FITSALEPRICE.
Any help would be GREATLY appreciated. This is driving me mad.
-
This topic was modified 3 years, 9 months ago by
ctmartin2020.
-
This topic was modified 3 years, 9 months ago by
-
P.S. I have even tried to change the price in the $product object before the add-to-cart even happens using $product->set_sale_price(<<MY NEW PRICE>>) but this does not seem to have any effect on the side cart — the value that shows in the cart is the original product price. Makes no sense. Hopefully I’m doing something stupid that can be easily fixed.
Update: I’ve now tried using $GLOBALS for the sale price and ID to pass into the action. Still doesn’t work. Here’s what DOES work:
add_action( 'woocommerce_before_calculate_totals', 'pricecartvariations', 1000, 1 ); function pricecartvariations( $cart ) { $pr = 500; // $pr = $GLOBALS['fit_sale_price'] DOES NOT WORK $pid = 1234; // $pid = $GLOBALS['fit_pid'] DOES NOT WORK foreach ($cart->get_cart() as $key=>$value) { if ($value['product_id'] == $pid) { $value['data']->set_price( $pr ); } } }
Obviously this is not what I want — to set the price of an items in the cart to $500 — but this is the ONLY thing that works.
So I guess the question now is, why are my $GLOBALS not coming through? Isn’t this a valid way to pass additional parameters into a filter or action?
Any help? The filter “woocommerce_add_cart_item_data” does not work either to relay new price info to the action “woocommerce_before_calculate_totals”.
So is this a case of the AJAX call for the side cart effectively being a new session, so none of this works? Is there a way? If not, just let me know and I will look for another plugin for the cart!
Hello,
The hook
woocommerce_before_calculate_totals
works fine with side cart. I have tested the below code.define('MYCONSTANT', 20); add_action( 'woocommerce_before_calculate_totals', 'pricecartvariations', 99 ); function pricecartvariations( $cart ) { foreach ($cart->get_cart() as $key=>$value) { $value['data']->set_price(MYCONSTANT); } }
Constants are different from $GLOBALS, if you have used function
define()
then you cannot use $GLOBALS to fetch it.
Now if you are still not able to get the constant value inside filter that means your constant is declared too late, after the filter is called.
Ajax is no different than the normal request.Also to make sure some other filter is not overriding yours, use priority
PHP_INT_MAX
instead of 99-
This reply was modified 3 years, 9 months ago by
xootix.
I will try the PHP_INT_MAX.
Of course, I’m not confusing globals with constants. I have tried both, neither work. My constants are being set before the user even “adds to cart”. But when I get into this filter, I cannot echo anything to see what is set but I suspect the constant values are reset based on the logic not executing. I have no idea why.
Also, if I do introduce caching, is there a particular endpoint URL I should exclude from the cache?
Ajax requests do not get cached, so you have nothing to worry about caching.
Also make sure the hook/place you’re using to define constant is available globally & is being executed. I am saying this because you have mentioned “My constants are being set before the user even “adds to cart”
The filterwoocommerce_before_calculate_totals
has nothing to do with “add to cart” functionality, it is for changing price in cart directly.
If you’re setting constants during “add to cart” event then it will not work.Thank you!
Ok, I set the action to priority “PHP_MAX_INT” but still didn’t help.
But if the constants are getting set after this action runs, I don’t understand how that could be the case. My constants are being set from within a filter function for Yoast SEO which runs at a priority of 10 (versus this action which has priority PHP_INT_MAX).
Here’s the trace:
#0 wp-content/themes/oem/functions.php(2032): quickfit(Array, 84693) #1 wp-includes/class-wp-hook.php(294): oem_yoast_meta_and_opengraph_description('Dirt Bike Front...') #2 wp-includes/plugin.php(212): WP_Hook->apply_filters('Dirt Bike Front...', Array) #3 wp-content/plugins/wordpress-seo/src/presenters/meta-description-presenter.php(59): apply_filters('wpseo_metadesc', 'Dirt Bike Front...', Object(Yoast\WP\SEO\Presentations\Indexable_Post_Type_Presentation)) #4 wp-content/plugins/wordpress-seo/src/presenters/abstract-indexable-tag-presenter.php(30): Yoast\WP\SEO\Presenters\Meta_Description_Presenter->get() #5 wp-content/plugins/wordpress-seo/src/presenters/meta-description-presenter.php(25): Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter->present() #6 wp-content/plugins/wordpress-seo/src/integrations/front-end-integration.php(299): Yoast\WP\SEO\Presenters\Meta_Description_Presenter->present() #7 wp-includes/class-wp-hook.php(292): Yoast\WP\SEO\Integrations\Front_End_Integration->present_head('') #8 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters('', Array) #9 wp-includes/plugin.php(484): WP_Hook->do_action(Array) #10 wp-content/plugins/wordpress-seo/src/integrations/front-end-integration.php(273): do_action('wpseo_head') #11 wp-includes/class-wp-hook.php(292): Yoast\WP\SEO\Integrations\Front_End_Integration->call_wpseo_head('') #12 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters(NULL, Array) #13 wp-includes/plugin.php(484): WP_Hook->do_action(Array) #14 wp-includes/general-template.php(3009): do_action('wp_head') #15 wp-content/themes/oem/header.php(28): wp_head() #16 wp-includes/template.php(730): require_once('/chroot/home/ad...') #17 wp-includes/template.php(676): load_template('/chroot/home/ad...', true, Array) #18 wp-includes/general-template.php(48): locate_template(Array, true, true, Array) #19 wp-content/plugins/elementor/modules/page-templates/templates/header-footer.php(9): get_header() #20 wp-includes/template-loader.php(106): include('/chroot/home/ad...') #21 wp-blog-header.php(19): require_once('/chroot/home/ad...') #22 index.php(17): require('/chroot/home/ad...') #23 {main}
#0 shows call to function in functions.php “quickfit” which is exactly where the constants are set — and I can echo them back from there to confirm it.
To further test this, I actually put the call to
quickfit()
(which sets the constants if they’re not already set) INTO thewoocommerce_before_calculate_totals
action function, and still I cannot get this working.So can you tell me if there is another action or filter I can use for my purposes?
DUH, wait, I’m reading this wrong. #0 is actually the last place in the queue. So I need to find a way to define these constants sooner. However, I do not understand why they are not being set when I run the code from within the action function itself!
Regardless, I don’t see any specific call to action
woocommerce_before_calculate_totals
but maybe that’s in an do_action array?Another thing that makes it nearly impossible for me to figure out what is going on is whenever there is an “echo” or print of any sort in the action function, the add-to-cart spins and spins in an endless loop and not only does the side cart not open but I get no output from my echo or print_r etc.
-
This reply was modified 3 years, 9 months ago by
ctmartin2020.
-
This reply was modified 3 years, 9 months ago by
ctmartin2020.
OK, I’m at the end of my rope here. It seems like
woocommerce_before_calculate_totals
— which seems like the most reasonable place to do this repricing — is running before I can set constants or globals to the values I need them to contain.Since I can’t use echo or print_r directly within the action function without crashing the page, I’m piping the output of my trace to a text file. So here’s what is happening (in reverse order) from the action function:
#0 wp-includes/class-wp-hook.php(292): pricecartvariations(Object(WC_Cart)) #1 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters(NULL, Array) #2 wp-includes/plugin.php(484): WP_Hook->do_action(Array) #3 wp-content/plugins/woocommerce/includes/class-wc-cart.php(1367): do_action('woocommerce_bef...', Object(WC_Cart)) #4 wp-content/plugins/side-cart-woocommerce/public/class-xoo-wsc-cart-data.php(71): WC_Cart->calculate_totals() #5 wp-includes/class-wp-hook.php(292): xoo_wsc_Cart_Data->set_ajax_fragments(Array) #6 wp-includes/plugin.php(212): WP_Hook->apply_filters(Array, Array) #7 wp-content/plugins/woocommerce/includes/class-wc-ajax.php(195): apply_filters('woocommerce_add...', Array) #8 wp-includes/class-wp-hook.php(292): WC_AJAX::get_refreshed_fragments('') #9 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters('', Array) #10 wp-includes/plugin.php(484): WP_Hook->do_action(Array) #11 wp-content/plugins/woocommerce/includes/class-wc-ajax.php(90): do_action('wc_ajax_get_ref...') #12 wp-includes/class-wp-hook.php(292): WC_AJAX::do_wc_ajax('') #13 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters(false, Array) #14 wp-includes/plugin.php(484): WP_Hook->do_action(Array) #15 wp-includes/template-loader.php(13): do_action('template_redire...') #16 wp-blog-header.php(19): require_once('/chroot/home/ad...') #17 index.php(17): require('/chroot/home/ad...') #18 {main}
I need to (1) check if this is a product page, (2) get the product id, then (3) lookup the pricing for the specific model the user is looking for (and apply that special pricing to the item added to the cart). It’s in this function
quickfit()
that I’m setting these constants I want to pull into thewoocommerce_before_calculate_totals
action… but when that gets called, they haven’t been defined yet (even though the priority is as high as it can possibly get!!!!).I’ve then tried to do this in an action like
template_redirect
(which is #15 in the list above, i.e. well before thewoocommerce_before_calculate_totals
action) but I get a fatal error asglobal $product; $product->get_id();
isn’t recognized (yet).Then I tried doing this in a filter like
woocommerce_add_to_cart_fragments
(#7 on the list above — also well before thewoocommerce_before_calculate_totals
action). I simply returned the $fragments parameter but before that inserted my logic to (1) check ifis_product()
and if so (2) get the product id and (3) lookup the pricing and set the constants etc. It never gets past theis_product()
check, so it looks like this is happening before woocommerce even knows this is a product.The info I need for my lookup is stored in the url. When I look at
$_SERVER['REQUEST_URI']
I do not see my own data… I only see the AJAX endpoint for the side cart.SO… where/how exactly can I pass the values that I need to change the pricing in the cart??? I’m really thinking this plugin is just not something a developer can work with as there don’t appear to be any hooks where I can modify the cart items.
-
This reply was modified 3 years, 9 months ago by
ctmartin2020.
-
This reply was modified 3 years, 9 months ago by
ctmartin2020.
SOLUTION: for those who encounter the same issue (…then good luck LOL!), there is a solution that appears to work. Set a session with an array of the data you want to pass into the
woocommerce_before_calculate_totals
action function when you’re dealing with an AJAX situation.Set it like this (substitute “_your_session_name” with whatever you like):
WC()->session->set( '_your_session_name', $data );
…where $data is an array of whatever data you want to store. You retrieve it like this:
$data = (array)WC()->session->get( '_your_session_name' );
-
This reply was modified 3 years, 9 months ago by
- The topic ‘Trying to change cart pricing’ is closed to new replies.