A specific WooCommerce product can only be by itself in the cart.
So how do I clear the cart while adding this specific product to the cart? and how can I remove this specific product from the cart when adding any other product?
I've figured out how to empty the cart when adding a specific product but I don't know how to remove this specific product from the cart when adding any other product.
The following will remove conditionally cart items based on a specific product:
When the specific product is added to cart, all other items are removed.
When any other product is added to cart, it removes the specific product (if it's in cart)
Here is the code:
// Remove conditionally cart items based on a specific product (item)
add_action( 'woocommerce_before_calculate_totals', 'remove_cart_items_conditionally', 10, 1 );
function remove_cart_items_conditionally( $cart ) {
// HERE define your specific product ID
$specific_product_id = 37;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$cart_items = $cart->get_cart(); // Cart items array
$items_count = count($cart_items); // Different cart items count
// Continue if cart has at least 2 different cart items
if ( $items_count < 2 )
return;
$last_item = end($cart_items); // Last cart item data array
$is_last_item = false; // Initializing
// Check if the specific product is the last added item
if ( in_array($specific_product_id, array( $last_item['product_id'], $last_item['variation_id'] ) ) ) {
$is_last_item = true;
}
// Loop through cart items
foreach ( $cart_items as $cart_item_key => $cart_item ) {
// Remove all others cart items when specific product ID is the last added to cart
if ( ! in_array($specific_product_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) && $is_last_item ) {
$cart->remove_cart_item( $cart_item_key );
}
// Remove the specific item when its is not the last added to cart
elseif ( in_array($specific_product_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) && ! $is_last_item ) {
$cart->remove_cart_item( $cart_item_key );
}
}
}
Code goes on function.php file of your active child theme (or active theme). Tested and works.
The above works perfectly! You can also add a notice to the cart once items have been removed to help with the user experience. Add this to the // Loop through cart items section in the first if statement:
wc_add_notice( __( 'Product XYZ has been removed from your cart because...', 'theme_domain' ), 'notice' );
Related
This question already has an answer here:
Woocomerce Remove a specific cart items when adding to cart another specific items
(1 answer)
Closed 2 years ago.
In Woocommerce, when I add a bundled product A I want to remove products B, C, D (single products that are already inside that bundle) and if product A (bundle) is in the cart, do not allow to add B, C or D products.
The answer Woocomerce Remove a specific cart items when adding to cart another specific items is very close of what I would like.
How can I do it backwards?
For the first condition you can indeed use the woocommerce_add_to_cart hook, for the 2nd condition you better use the woocommerce_add_to_cart_validation hook.
So we apply both conditions together and we get
function filter_woocommerce_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = null, $variations = null ) {
// Set ID's
$product_a = 30;
$product_b_c_d = array ( 813, 815, 817 );
// Get current product id
$product_id = $variation_id > 0 ? $variation_id : $product_id;
// Product A is added
if ( $product_a == $product_id ) {
// Loop trough cart items
foreach( WC()->cart->get_cart() as $key => $item ) {
// Product ID is in array
if ( in_array( $item['product_id'], $product_b_c_d ) ) {
// Remove cart item(s)
WC()->cart->remove_cart_item( $key );
}
}
// Optionaly displaying a notice
wc_add_notice( __( 'Product A is added, Product B, C or D has been removed from cart.', 'woocommperce' ), 'notice' );
}
// Product B, C or D is added
elseif ( in_array( $product_id, $product_b_c_d ) ) {
// Generate card id
$product_cart_id = WC()->cart->generate_cart_id( $product_a );
// Check if product A in the cart
$item_key = WC()->cart->find_product_in_cart( $product_cart_id );
// if item_key true
if ( $item_key ) {
// Optionaly displaying a notice
wc_add_notice( __( 'Product A is in cart, Product B, C or D are not allowed', 'woocommerce' ), 'error' );
$passed = false;
}
}
// Return
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'filter_woocommerce_add_to_cart_validation', 10, 5 );
For a specific bundled product, the code below will:
remove any individual child products when bundle product is added to cart
avoid individual child products to be added to cart when the bundle product is already in cart.
So one hooked function for each case, will be a lighter process:
// When the bunddle product is added to cart remove single components from cart
add_action( 'woocommerce_add_to_cart', 'on_bundled_product_added_to_cart', 10, 4 );
function on_bundled_product_added_to_cart( $cart_item_key, $product_id, $quantity, $variation_id ) {
// SETTINGS
$bundled_product_id = 83; // Set HERE your bundled product ID
$item_ids_to_remove = array(37, 53, 31); // Set HERE the product ID(s) to remove(s)
$removed_items = 0; // Initializing
// When the bundled product is added to cart
if( $bundled_product_id == $product_id ) {
// Loop through cart items
foreach( WC()->cart->get_cart() as $item_key => $cart_item ){
// Get the cart item keys of the items to be removed
if( array_intersect( array($cart_item['product_id'], $cart_item['variation_id']), $item_ids_to_remove ) ) {
WC()->cart->remove_cart_item($item_key);
$removed_items++;
}
}
}
// Optionaly displaying a notice for the removed items
if( ! empty($removed_item_names) ){
wc_add_notice( sprintf( __( 'Some products have been removed from cart as they are already bundled in your cart', 'woocommerce' ), $items_text ), 'notice' );
}
}
// Add to cart validation for bundled components
add_filter( 'woocommerce_add_to_cart_validation', 'check_cart_items_for_bundle_product', 9999, 4 );
function check_cart_items_for_bundle_product( $passed, $product_id, $quantity, $variation_id = 0 ) {
// SETTINGS
$bundled_product_id = 83; // Set HERE your bundled product ID
$bundled_items_ids = array(37, 53, 31); // Set HERE the bundled items ID(s) from the bundled product
$bundled_in_cart = false;
if( ! WC()->cart->is_empty() ) {
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ){
// check for bundled product
if( $bundled_product_id == $cart_item['product_id'] ) {
$bundled_in_cart = true;
break;
}
}
if( $bundled_in_cart && array_intersect(array($product_id, $variation_id), $bundled_items_ids) ) {
// Add a custom notice
wc_add_notice( __( 'This product is already a component of the bundled product in your cart', 'woocommerce' ), 'error' );
return false;
}
}
return $passed;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
The message error when trying to add to cart a component of a bundled product when it's in cart already:
The message when components of a bundled product are in cart and they are removed when adding the parent bundled product (in cart page):
Description:
I have use case where I need to check if a specific product has been added to cart before customer adds another products to cart.
Background:
We are renting products out based on packages(which are products). Packages include multiple products and products do not have price, packages do. So basically you would need to add a package(with price) and products(with no price) to cart.
Problem:
At the moment customers can add products before packages and they can continue to shopping cart with total zero.
Some of the progress what I have:
if ( ! WC()->cart->is_empty() )
foreach( WC()->cart->get_cart() as $cart_item )
// now i would need to check if cart consists a package
And i could solve adding product to cart with no package in cart like this:
if (WC()->cart->is_empty() )
//then don't add product to cart, tell customer to add package first.
Use the woocommerce_add_to_cart_validation hook
Comment with explanation added in the code
function filter_woocommerce_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = null, $variations = null ) {
// Product (ID) in cart
$product_first_in_cart = 30;
// Compare
if ( $product_first_in_cart != $product_id ) {
// Set variable
$in_cart = false;
// Cart NOT empty
if ( ! WC()->cart->is_empty() ) {
// Loop trough cart
foreach( WC()->cart->get_cart() as $cart_item ) {
// Search for the specific product
if ( $cart_item['data']->get_id() == $product_first_in_cart ) {
// Found, break loop
$in_cart = true;
break;
}
}
}
// NOT in cart
if ( ! $in_cart ) {
wc_add_notice( __( 'Please add product "A" before adding other products', 'woocommerce' ), 'error' );
$passed = false;
}
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'filter_woocommerce_add_to_cart_validation', 10, 5 );
I would like to alter a specific product in Woocommerce, adding programmatically to its original an amount of $10, EXCEPT in those cases:
On specific product pages that are bookable products for hire (Woocommerce Bookings) that belongs to a certain Category "C".
If any cart item belongs to that category "C".
I was using this answer code to one of my questions until now. But I should need to display this specific product altered price everywhere except on that product pages that are bookable products, in front end.
I have also this code that displays the Force Sells price beside the titles. This should still show the specific product original price on that product pages that are bookable products in the Force Sells section:
function wc_forcesells_product_price( $name, $product ) {
// Only in single product pages
if( ! is_product() ) return $name;
// The product name + the product formatted price
return $name . ' (' . wc_price( wc_get_price_to_display( $product ) ) . ')';
}
add_filter( 'woocommerce_product_title', 'wc_forcesells_product_price', 20, 2 );
Reference for above: Add price beside Woocommerce Force Sells.
Updated to handle multiple product Ids if necessary
Try the following that will display for a specific product ID a custom price everywhere except:
On booking products to hire pages
When a product category is in cart
The code will also change this custom product price in cart items except when a specific product category is in cart items.
You will have to set in those functions:
This specific product ID
The booking products IDs to hire
The Additional price amount
The product category (Id slug or name)
The code:
// Change product ID 87 price everywhere on front end EXCEPT:
// - On booking products to hire pages
// - When a product category is in cart
add_filter( 'woocommerce_get_price_html', 'product_id_87_displayed_price', 10, 2 );
function product_id_87_displayed_price( $price_html, $product ) {
// Only for product ID 87
if( in_array( $product->get_id(), array( 87, 2799 ) ) ){
return $price_html; // Exit
// HERE set booking products IDs to hire in the array
$product_ids_to_hire = array( 53, 738 );
// HERE set your product category term ID, slug or name
$product_category = 'hoodies';
// HERE set the price additional amount
$addp = 10;
// EXCEPT on booking products to hire pages
if( is_single($product_ids_to_hire) ) return $price_html; // Exit
// Checking for the product category in cart items loop
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( has_term( $product_category, 'product_cat', $cart_item['product_id'] ) )
return $price_html; // Product category found ==> Exit
}
if ( '' !== $product->get_price() && ! $product->is_on_sale() ) {
$price_html = wc_price( wc_get_price_to_display( $product ) + $addp ) . $product->get_price_suffix();
}
return $price_html;
}
// Add custom calculated price to cart item data for product ID 87
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_simple_product_custom_price', 20, 2 );
function add_cart_simple_product_custom_price( $cart_item_data, $product_id ){
// Only for product ID 87
if( ! in_array( $product->get_id(), array( 87 ) ) )
return $cart_item_data; // Exit
// HERE set the price additional amount
$addp = 10;
$product = wc_get_product($product_id); // The WC_Product Object
$price = (float) $product->get_price(); // The product price
// Set the custom amount in cart object
$cart_item_data['new_price'] = $price + $addp;
return $cart_item_data;
}
// Set custom calculated price to cart for product ID 87
add_action( 'woocommerce_before_calculate_totals', 'set_cart_simple_product_custom_price', 20, 1 );
function set_cart_simple_product_custom_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// HERE set your product category term ID, slug or name
$product_category = 'hoodies';
// 1st cart items Loop: checking for the product category
foreach ( $cart->get_cart() as $cart_item ) {
if ( has_term( $product_category, 'product_cat', $cart_item['product_id'] ) )
return; // Product category found ==> We EXIT from this function
}
// 2nd Loop: Changing cart item prices (Product category not found)
foreach ( $cart->get_cart() as $cart_item ) {
if( isset($cart_item['new_price']))
$cart_item['data']->set_price( $cart_item['new_price'] );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
It should also work with your wc_forcesells_product_price() function.
I am trying to set the functionality in Woocommerce on the Add to Cart button to only allow a particular product to be added once to the Cart.
Once a particular product has been added to cart the first time, the Add to Cart needs to be hidden.
In the cart I can have any number of products - just a max of quantity 1 for each product.
I was doing research and saw that I can use woocommerce_add_to_cart_validation hook. But have no idea how to start off.
How can I allow a particular product to be added once to the Cart?
Disable add to cart button if product is in cart using woocommerce_is_purchasable hook:
add_filter( 'woocommerce_is_purchasable', 'disable_add_to_cart_if_product_is_in_cart', 10, 2 );
function disable_add_to_cart_if_product_is_in_cart ( $is_purchasable, $product ){
// Loop through cart items checking if the product is already in cart
foreach ( WC()->cart->get_cart() as $cart_item ){
if( $cart_item['data']->get_id() == $product->get_id() ) {
return false;
}
}
return $is_purchasable;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works (even for product variations in variable products).
Original answer:
Here is an example using woocommerce_add_to_cart_validation hook and that will do the trick (preventing add to cart action and displaying a custom notice when needed), and using a custom utility function that will remove quantity field for your specific defined product ID:
add_filter( 'woocommerce_add_to_cart_validation', 'limit_cart_items_from_category', 10, 3 );
function limit_cart_items_from_category ( $passed, $product_id, $quantity ){
// HERE define your product ID
$targeted_product_id = 37;
// Check quantity and display notice
if( $quantity > 1 && $targeted_product_id == $product_id ){
wc_add_notice( __('Only one item quantity allowed for this product', 'woocommerce' ), 'error' );
return false;
}
// Loop through cart items checking if the product is already in cart
foreach ( WC()->cart->get_cart() as $cart_item ){
if( $targeted_product_id == $product_id && $cart_item['data']->get_id() == $targeted_product_id ) {
wc_add_notice( __('This product is already in cart (only one item is allowed).', 'woocommerce' ), 'error' );
return false;
}
}
return $passed;
}
// Checking and removing quantity field for a specific product
add_filter( 'woocommerce_quantity_input_args', 'custom_quantity_input_args', 10, 2 );
function custom_quantity_input_args( $args, $product ) {
// HERE define your product ID
$targeted_product_id = 37;
if( $targeted_product_id == $product->get_id() )
$args['min_value'] = $args['max_value'] = $args['input_value'] = 1;
return $args;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
My WordPresss related task is simple, but I can't find the solution. I have 2 products in my woocommerce shop, and I would like to show both of them on the cart-page in the woocommerce table, let the customer set the quantity of them. If the customer don't want to buy something, just leave it on 0.
The problem is the cart table is not shown if it is empty and I can only see the items that I put in there.
you can add product like that and add condition according you i set for admin and product id. change product id with your product id
/*
* goes in theme functions.php or a custom plugin
**/
// add item to cart on visit
add_action( 'template_redirect', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
$product_id = 64;
$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 );
}
}
}