So I need a little help. I have a wooocommerce webshop where there are two main products, and then 3 products, that visitors only will be able to buy, if one of the two main products are in the cart. I have found some code, that works like this: If I remove a main product, the additional product will be removed automatic, which it should. My problem is, i dont know how to modify the code, so it includes 3 products id's (one id, for each of the additional products). I have tried plenty of things, but cant get it to work. Can you maybe help me? This it the code I have (which now contains one product id, and it should contain three id's):
// Add to cart validation for the discounted product
add_filter( 'woocommerce_add_to_cart_validation', 'check_specific_discounted_product', 10, 3 );
function check_specific_discounted_product( $passed, $product_id, $quantity ) {
// Settings
$discounted_product_id = 3008;
if( WC()->cart->is_empty() && $discounted_product_id == $product_id ) {
wc_add_notice( __("This product can't be purchased alone."), 'notice' );
return false;
}
return $passed;
}
// Removing the discounted product if it's alone in cart
add_action( 'woocommerce_before_calculate_totals', 'conditionally_remove_a_discounted_product' );
function conditionally_remove_a_discounted_product( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Settings
$discounted_product_id = 3008;
// Initializing variables
$discounted_item_key = false;
// Loop through cart items (first loop)
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// When free productis is cart
if ( in_array( $discounted_product_id, array($cart_item['product_id'], $cart_item['variation_id']) ) ) {
$discounted_item_key = $cart_item_key;
}
// if any other product is in cart: EXIT
else {
return;
}
}
// When the discounted product is alone in cart, remove it
if( $discounted_item_key ) {
// display notice on removal (optional)
wc_clear_notices();
wc_add_notice( __("The discounted product can't be purchased alone and has been removed."), 'notice' );
$cart->remove_cart_item( $discounted_item_key ); // Remove
}
}
I have tried to modify the code like this:
$discounted_product_id = 3004, 3008, 3157;
And like this:
$discounted_product_id = 3004;$discounted_product_id = 3008;$discounted_product_id = 3157;
Also like this:
$discounted_product_id = array('3004','3008','3157');
But it's not working :(
Related
I have two different product and two different category and i have this code.
add_action( 'woocommerce_before_calculate_totals', 'auto_add_item_based_on_product_category', 10, 1 );
function auto_add_item_based_on_product_category( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$required_categories = array('Floor Forever Vinyl', 'Parapety'); // Required product category(ies)
$added_product_id_1 = 1773; // Specific product to be added automatically
$added_product_id_2 = 1774; // Specific product to be added automatically
$matched_category = false;
// Loop through cart items
foreach ( $cart->get_cart() as $item_key => $item ) {
// Check for product category
if( has_term( $required_categories, 'product_cat', $item['product_id'] ) ) {
$matched_category = true;
}
// Check if specific product is already auto added
if( $item['data']->get_id() == $added_product_id_1 ) {
$saved_item_key_1 = $item_key; // keep cart item key
}
if( $item['data']->get_id() == $added_product_id_2 ) {
$saved_item_key_2 = $item_key; // keep cart item key
}
}
// If specific product is already auto added but without items from product category
if ( isset($saved_item_key_1) && ! $matched_category ) {
$cart->remove_cart_item( $saved_item_key_1 ); // Remove specific product
}
// If there is an item from defined product category and specific product is not in cart
elseif ( ! isset($saved_item_key_1) && $matched_category ) {
$cart->add_to_cart( $added_product_id_1 ); // Add specific product
}
// If specific product is already auto added but without items from product category
if ( isset($saved_item_key_2) && ! $matched_category ) {
$cart->remove_cart_item( $saved_item_key_2 ); // Remove specific product
}
// If there is an item from defined product category and specific product is not in cart
elseif ( ! isset($saved_item_key_2) && $matched_category ) {
$cart->add_to_cart( $added_product_id_2 ); // Add specific product
}
}
But adding products from both categories will add the giant product IDs 1773 and 1774.
I need help to make sure that for the Floor Forever Vinyl category there is only a product with ID 1773 and for the Sills category there is only a product with ID 1774. Thank you in advance for your help.
I hope you can help me out.
I need to check the SKU before saving a new product
And I also want to avoid errors due to duplicated SKU value. The SKU should just be change so it is unique.
I have tried a lot of combinations and different hooks – and nothing happens, the product just saves whether or not the SKU is set.
// Disable default duplicte sku check
add_filter( 'wc_product_has_unique_sku', '__return_false' );
//Check SKU
add_action( 'woocommerce_before_product_object_save', 'set_sku', 50, 2 );
function set_sku( $product_id, $product ) {
function generateRandomString($length = 10) {
return substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,$length);
}
$currentSku = $product->get_sku();
if( empty( $currentSku ) ) { //If SKU field is empty then use slug for SKU
$product->set_sku($product->get_slug());
}else if( !wc_product_has_unique_sku($product_id, $currentSku ) ) {
$product->set_sku($currentSku.'-'.$generateRandomString()); //SKU duplicated - add random string to end
}
}
Why don't you just use the 'pre_post_update' hook?
The hook 'woocommerce_before_product_object_save' doesn't work, it was probably removed.
add_action( 'pre_post_update', 'set_sku', 50, 2 );
function set_sku( $product_id, $product_data ) {
// Only run this code for products
if ($product_data['post_type'] !== 'product') {
return;
}
$product = wc_get_product($product_id);
//... your sku related code ...
I already found this code here and it works for like 80/90% for me (see below).
This code adds 60 euro to my cart when there is a product from category ID 349 in the cart. When I add a product from that category to my cart when the cart is empty it works fine. But when there is already a product in my cart from a different category and then I add the product with category 349 it doesn't add the 60 euro extra fee. How is this possible?
function woo_add_cart_fee() {
$category_ID = '349';
global $woocommerce;
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
// Get the terms, i.e. category list using the ID of the product
$terms = get_the_terms( $values['product_id'], 'product_cat' );
// Because a product can have multiple categories, we need to iterate through the list of the products category for a match
foreach ($terms as $term) {
// 349 is the ID of the category for which we want to remove the payment gateway
if($term->term_id == $category_ID){
$excost = 60;
}
}
$woocommerce->cart->add_fee('Extra bezorgkosten kunstgras', $excost, $taxable = false, $tax_class = '');
}
}
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );
The code you are using is a bit outdated and you should use has_term() Wordpress conditional function to target a product category this way:
add_action( 'woocommerce_cart_calculate_fees','custom_pcat_fee', 20, 1 );
function custom_pcat_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Set HERE your categories (can be term IDs, slugs or names) in a coma separated array
$categories = array('349');
$fee_amount = 0;
// Loop through cart items
foreach( $cart->get_cart() as $cart_item ){
if( has_term( $categories, 'product_cat', $cart_item['product_id']) )
$fee_amount = 60;
}
// Adding the fee
if ( $fee_amount > 0 ){
// Last argument is related to enable tax (true or false)
WC()->cart->add_fee( __( "Extra bezorgkosten kunstgras", "woocommerce" ), $fee_amount, false );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
A fee of 60 will always be added if there is in cart an item from 349 product category ID.
I found a solution like the following. Note that I kept adding a fee, because I started from a previous snippet. You can apply an existing discount or calculate a different total according to your needs.
In this case, I apply a negative fee - like a discount - according to a >= 300 total value of the cart, whose values would be -25% only for local_pickup shipping method, calculating taxes in addition.
function discount_to_cat(){
// thanks to LoicTheAztec's snippet
$cat_in_cart = false;
// Loop through all products in the Cart
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( has_term( 'category_to_pick', 'product_cat', $cart_item['product_id'] ) ) {
$cat_in_cart = true;
$tot_category_price = $cart_item['data']->get_price();
$tot_category_qty = $cart_item['quantity'];
$tot_category = $tot_category_price * $tot_category_qty;
break;
}
} global $product;
$total = WC()->cart->subtotal;
$discount_label = "";
if($total >= 300){
$discount_label=15;
}
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = explode(':',$chosen_methods[0]);
if($chosen_shipping[0]=='local_pickup'){
$discount_label=25;
}
$discount_applied = ($total-$tot_category)*$discount_label/100;
if($discount_label!=""){
$discount_applied_net = ($discount_applied/1.1); //1.1 according taxes for shipping
WC()->cart->add_fee( "Discount applied: ($discount_label%)", -$discount_applied_net, false );
}
}
add_action( 'woocommerce_cart_calculate_fees','discount_to_cat' );
I'm working on woocommerce API plugin development and trying to pass custom cart item data using the below code in add to cart API endpoint.
$cart_item_key = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations, array('margin' => 200));
and want to use that custom cart item data on woocommerce_before_calculate_totals hook (see code below) but can't getting custom cart item data ($cart_item['margin']) there.
add_action( 'woocommerce_before_calculate_totals', 'custom_cart_item_price', 30, 1 );
function custom_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
foreach ( $cart->get_cart() as $cart_item ) {
if( isset($cart_item['margin']) ){
$final_price = ($cart_item['data']->get_price() + $cart_item['margin']);
$cart_item['data']->set_price($final_price);
}
}
}
I have installed Woocommerece 4.9 version, please help me to solve this issue.
Thanks in advance.
I had kind of the same problem, the issue was there was another plugin that might have a higher priority on the filter. It was a Role based pricing plugin, after deactivating it, everything worked. So just check if there is no other thing overwriting the function.
To do a test I used the woocommerce_add_to_cart_validation hook and I added a product to cart with add_to_cart() method of the WC_Cart class.
add_action( 'woocommerce_add_to_cart_validation', 'add_product_to_cart_programmatically', 10, 3 );
function add_product_to_cart_programmatically( $passed, $product_id, $quantity) {
$product_id = 166; // product id to add
$quantity = 10; // quantity product to add
WC()->cart->add_to_cart( $product_id, $quantity, 0, array(), array( 'margin' => 200 ) );
return $passed;
}
Once the product has been added to the cart, I can apply a custom price based on the custom cart item data:
add_action( 'woocommerce_before_calculate_totals', 'custom_cart_item_price', 30, 1 );
function custom_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
foreach ( $cart->get_cart() as $cart_item ) {
if ( isset( $cart_item['margin'] ) && ! empty( $cart_item['margin'] ) ) {
$final_price = $cart_item['data']->get_price() + $cart_item['margin'];
$cart_item['data']->set_price( $final_price );
}
}
}
As recommended by #danielsalare you can try to increase the priority of the action, as in my example above.
I had a similar problem and found this solution: First, we add the custom products to Woocommerce. Second, we generate an identifier (ID), and later we add it.
for example, obtain product-id trow a with $_POST
$myProduct = $_POST['myProduct'];
$myProduct_id = WC()->cart->generate_cart_id($myProduct);
if (!WC()->cart->find_product_in_cart($myProduct_id )) {
WC()->cart->add_to_cart($myProduct);
}
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;
}
}