I am trying to programmatically update the quantity of a specific product in the cart if certain criteria is met.
I can easily update the price of the cart items with the following:
add_action( 'woocommerce_before_calculate_totals', 'wwpa_simple_add_cart_price' );
function wwpa_simple_add_cart_price( $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
$value['data']->price = '1';
}}
In the function above I tried to add:
$value['data']->quantity= '10';
This doesn't work but not quite sure how or if I can edit the quantity?
I also tried a these combinations that I found while digging around WooCommerce:
$value['data']->quantity= '10';
$value['data']->qty= '10';
$value['quantity'] = '10';
Again none of these worked.
There has been some changes to the WC_Cart class since this post originally got posted, so i updated it with the new changes.
To update the quantity:
WC()->cart->set_quantity($cart_item_key, 100);
How to get the $cart_item_key example:
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
echo $cart_item_key;
}
And another example with a known cart_item_key:
WC()->cart->set_quantity('8d317bdcf4aafcfc22149d77babee96d', 100);
Hope this helps:)
Related
I am trying to change product price in cart using the following function:
add_action( 'woocommerce_before_shipping_calculator', 'add_custom_price'
);
function add_custom_price( $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
$value['data']->price = 400;
}
}
It was working correctly in WooCommerce version 2.6.x but not working anymore in version 3.0+
How can I make it work in WooCommerce Version 3.0+?
Thanks.
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 to 1000 (or even 2000) 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
With WooCommerce version 3.2.6, #LoicTheAztec's answer works for me if I increase the priority to 1000.
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);
I tried priority values of 10,99 and 999 but the price and total in my cart did not change (even though I was able to confirm with get_price() that set_price() had actually set the price of the item.
I have a custom hook that adds a fee to my cart and I'm using a 3rd party plugin that adds product attributes. I suspect that these WooCommerce "add-ons" introduce delays that require me to delay my custom action.
This question already has answers here:
Sorting order items by SKU in Woocommerce
(2 answers)
Closed 2 years ago.
I'm stumped if it's possible. I have scouted to only seeing results to sort by SKU on the front end. not the backend. When you edit an order, I want there to be an SKU column that I can sort by ASC/DESC. Is there a plugin out there that achieves this, or a snippet of code that can add in an additional column? Any help would be greatly appreciated. Below is an image illustrating the SKU I'm talking about and would love for it to be moved/duplicated into its own column
add_filter( 'woocommerce_order_get_items', 'filter_order_get_items', 10, 3 );
function filter_order_get_items( $items, $order, $types = 'line_item' ) {
if(count($items) < 2) return $items;
if( $types != 'line_item') return $items;
$item_skus = $sorted_items = array();
// Loop through order line items
foreach( $items as $items_id => $item ){
// Check items type: for versions before Woocommerce 3.3
if($item->is_type('line_item')){
$product = $item->get_product(); //
$item_skus[$product->get_sku()] = $items_id;
}
}
// Check items type: for versions before Woocommerce 3.3 (2)
if( count($item_skus) == 0 ) return $items;
// Sorting in ASC order based on SKUs;
ksort($item_skus); // or use krsort() for DESC order
// Loop through sorted $item_skus array
foreach( $item_skus as $sku => $item_id ){
// Set items in the correct order
$sorted_items[$item_id] = $items[$item_id];
}
return $sorted_items;
}
#mujuonly has a great answer. I was using it until I found a conflict with woocommerce subscription renewals. The original orders were fine, but renewals orders were missing their shipping method.
Instead I opted to sort the basket items by sku so that they would be saved in the database that way.
add_action( 'woocommerce_cart_loaded_from_session', 'sort_cart_items_sku' );
function sort_cart_items_sku() {
// READ CART ITEMS
$products_in_cart = array();
foreach ( WC()->cart->get_cart_contents() as $key => $item ) {
$products_in_cart[ $key ] = $item['data']->get_sku();
}
// SORT CART ITEMS
natsort( $products_in_cart );
// ASSIGN SORTED ITEMS TO CART
$cart_contents = array();
foreach ( $products_in_cart as $cart_key => $product_title ) {
$cart_contents[ $cart_key ] = WC()->cart->cart_contents[ $cart_key ];
}
WC()->cart->cart_contents = $cart_contents;
}
Credit: https://businessbloomer.com/woocommerce-sort-cart-items-alphabetically-az/
Basically I am interested in using woocommerce to sell a product . This product is a Print Order of a external printing service that I have implemented in a brand new plugin.
What I want now is after the order, is to be able to put that "order" in the buy cart, and buy it normally as just another woocommerce product.
The product has to be created on the fly, manually by a way of some function that I can use to create a product during a certain workflow point.
Can you help me to find a solution?
Using woocommerce or not!
What i understand from your requirement/comments is that you want to be able to dynamically create a product, which is bad idea. But here is my suggestion.
Lets say you have a simple product called "Print Job" with a price of $1 and with an id of 10. And i am supposing that your external printing service would send back a response with the order and the price of printing, lets say $64.
Once you recieve the response you can simply call add_product_to_cart(10), this will automatically add the print job product to your cart.
/************* functions.php ***************/
function add_product_to_cart($product_id) {
if ( ! is_admin() ) {
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
You also need to add this function in your functions.php, this function will override the price of the product i.e "Print Job" with the actual price of $64.
/******************* Functions.php ****************/
add_action( 'woocommerce_before_calculate_totals', 'override_printing_price' );
function override_printing_price( $cart_object ) {
$custom_price = 64;
foreach ( $cart_object->cart_contents as $key => $value ) {
$value['data']->price = $custom_price;
}
}
I think this code should work but not exactly sure where to place it. Everywhere I have tried has failed so far...
add_action('init', 'woocommerce_clear_cart');
function woocommerce_clear_cart() {
global $woocommerce, $post, $wpdb;
$url = explode('/', 'http://'.$_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
$slug=$url[4];
$postid = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_status='publish' AND post_name = '$slug'");
if ($postid){
if ($postid == PRODUCTID1 || $postid == PRODUCTID2){
$woocommerce->cart->empty_cart();
}
}
}
Unfortunately there is no 'action' hook before WooCommerce adds an item to the cart. But they have a 'filter' hook before adding to cart.
That is how I use it:
add_filter( 'woocommerce_add_cart_item_data', 'woo_custom_add_to_cart' );
function woo_custom_add_to_cart( $cart_item_data ) {
global $woocommerce;
$woocommerce->cart->empty_cart();
// Do nothing with the data and return
return $cart_item_data;
}
Based on the accepted answer and the latest Woo version 2.5.1 I updated the function to be slightly cleaner using the code woo uses in class-wc-checkout.php to clear the cart
add_filter( 'woocommerce_add_cart_item_data', '_empty_cart' );
function _empty_cart( $cart_item_data ) {
WC()->cart->empty_cart();
return $cart_item_data;
}
There is a filter/hook that runs before an item is added to the cart as each product goes through validation before it is added.
So when validating a product, we can check if the item if there are already items in the cart and clears those (if the current item is able to be added) and adds an error message.
/**
* When an item is added to the cart, remove other products
*/
function so_27030769_maybe_empty_cart( $valid, $product_id, $quantity ) {
if( ! empty ( WC()->cart->get_cart() ) && $valid ){
WC()->cart->empty_cart();
wc_add_notice( 'Whoa hold up. You can only have 1 item in your cart', 'error' );
}
return $valid;
}
add_filter( 'woocommerce_add_to_cart_validation', 'so_27030769_maybe_empty_cart', 10, 3 );
This worked like a charm for me, removes the previous product and adds the new one with the new product configuration. Cheers
Update: For WooCommerce 3.0.X
function check_if_cart_has_product( $valid, $product_id, $quantity ) {
if(!empty(WC()->cart->get_cart()) && $valid){
foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
$_product = $values['data'];
if( $product_id == $_product->get_id() ) {
unset(WC()->cart->cart_contents[$cart_item_key]);
}
}
}
return $valid;
}
add_filter( 'woocommerce_add_to_cart_validation', 'check_if_cart_has_product', 10, 3 );
For WooCommerce version less than 3.0.X
function check_if_cart_has_product( $valid, $product_id, $quantity ) {
if(!empty(WC()->cart->get_cart()) && $valid){
foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
$_product = $values['data'];
if( $product_id == $_product->id ) {
unset(WC()->cart->cart_contents[$cart_item_key]);
}
}
}
return $valid;
}
add_filter( 'woocommerce_add_to_cart_validation', 'check_if_cart_has_product', 10, 3 );
You have two options:
WooCommerce Min/Max Quantities extension
The following code added to your functions.php theme file
add_filter ( 'woocommerce_before_cart' , 'allow_single_quantity_in_cart' );
function allow_single_quantity_in_cart() {
global $woocommerce;
$cart_contents = $woocommerce->cart->get_cart();
$keys = array_keys ( $cart_contents );
foreach ( $keys as $key ) {
$woocommerce->cart->set_quantity ( $key, 1, true );
}
}
Don't add functions directly to your commerce files...you'll lose all your code when you update.
User functions should always be hooked through the functions.php of your theme.
Add this to your child-themes functions.php (tested in 2022, requires PHP 7 or higher):
add_filter('woocommerce_add_cart_item_data', function($cart_data) {
wc_empty_cart();
return $cart_data;
}, 99);
The "woocommerce_add_cart_item_data" filter fires every time a new item is added to the cart. We use this chance to call "wc_empty_cart" which empties the cart and optionally the persistent cart too. The new items is therefore alone in the cart.
Try this,
For removing the all products from the cart and adding the last added one,
//For removing all the items from the cart
global $woocommerce;
$woocommerce->cart->empty_cart();
$woocommerce->cart->add_to_cart($product_id,$qty);
class file is wp-content/plugins/woocommerce/classes/class-wc-cart.php.
You can add the above code on the add to cart function in functions.php.
Hope its works..
Eu coloco na function.php do tema, o que faço ou no woocomerce
function check_if_cart_has_product( $valid, $product_id, $quantity ) {
if(!empty(WC()->cart->get_cart()) && $valid){
foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
$_product = $values['data'];
if( $product_id == $_product->id ) {
wc_add_notice( 'The product is already in cart', 'error' );
return false;
}
}
}
return $valid;
}
add_filter( 'woocommerce_add_to_cart_validation', 'check_if_cart_has_product', 10, 3 );
On WordPress 5.6.1. no need to add a custom filter or write code there is an option to limit one product add to the cart.
I have develop shoping cart in wordpress using Woocommerce plugin. I need to display products in the cart order by product price please help me to do this
thanks
To order products low to high or high to low price in the Woocommerce cart, try adding the following to your functions.php file (or plugin):
function 12345_cart_updated() {
$products_in_cart = array();
// Assign each product's price to its cart item key (to be used again later)
foreach ( WC()->cart->cart_contents as $key => $item ) {
$product = wc_get_product( $item['product_id'] );
$products_in_cart[ $key ] = $product->get_price();
}
// SORTING - use one or the other two following lines:
asort( $products_in_cart ); // sort low to high
// arsort( $products_in_cart ); // sort high to low
// Put sorted items back in cart
$cart_contents = array();
foreach ( $products_in_cart as $cart_key => $price ) {
$cart_contents[ $cart_key ] = WC()->cart->cart_contents[ $cart_key ];
}
WC()->cart->cart_contents = $cart_contents;
}
add_action( 'woocommerce_cart_loaded_from_session', '12345_cart_updated' );
This function is similar and derived from one seen at https://businessbloomer.com/woocommerce-sort-cart-items-alphabetically-az/ which is nearly identical to this earlier-posted function: https://gist.github.com/maxrice/6541634
In most cases, for manipulating data on the WordPress ecosystem, the answer will be wp filter, no wp action.
In addition, WC_car.cart_contents array, hold the product object it's self on $cart_contents['data']; //WC_Product_Object, So we didn't need to get product again.
Simple filter to order by price:
PHP 7.4+
add_filter( 'woocommerce_get_cart_contents', 'prefix_cart_items_order' );
function prefix_cart_items_order( $cart_contents ) {
uasort($cart_contents,
fn($a, $b) =>
$a['data']->get_price() < $b['data']->get_price() ? -1 : 1
);
return $cart_contents;
}
PHP < 7
add_filter( 'woocommerce_get_cart_contents', 'prefix_cart_items_order' );
function prefix_cmp ($a, $b) {
return $a['data']->get_price() < $b['data']->get_price() ? -1 : 1;
}
function prefix_cart_items_order( $cart_contents ) {
uasort($cart_contents, 'prefix_cmp');
return $cart_contents;
}
mmmm, Is right there on the Woo admin page!!
Woocommerce - > Adjustments - > Catalogue - > Default Products Ordering