I am a beginner trying to learn Wordpress and have a variable product with prices:
cod Rs 250
online Rs 200
I want to use the minimum price in my themes functions.php.
How will I be able to fetch or get the minimum value?
I want to use in the below code :
function filter_gateways($gateways){
$payment_NAME = 'cod'; //
$min_variation_price = ''; <--------------- minimum variation price
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) {
// 20 is the ID of the category for which we want to remove the payment gateway
if($term->term_id == $min_variation_price){
unset($gateways[$payment_NAME]);
// If you want to remove another payment gateway, add it here i.e. unset($gateways['cod']);
break;
}
break;
}
}
return $gateways;
}
To get the minimum variation active price in WooCommerce from a WC_Product_Variable object:
$variation_min_price = $product->get_variation_price();
It seems that you are trying here to unset 'cod' payment gateway when a cart item min variation price is matching with his product category ID.
Using the WordPress conditional function has_term() will really simplify your code (it accepts term Ids, term slugs or term names for any taxonomy (as 'product_cat' here for product categories).
I suppose that your function is hooked in woocommerce_available_payment_gateways filter hook…
I made some changes in your code as it's a bit outdated and with some errors:
add_filter('woocommerce_available_payment_gateways', 'conditional_payment_gateways', 10, 1);
function conditional_payment_gateways( $available_gateways ) {
// Not in backend (admin)
if( is_admin() )
return $available_gateways;
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// Get the WC_Product object
$product = wc_get_product($cart_item['product_id']);
// Only for variable products
if($product->is_type('variable')){
// Get the Variation "min" price
$variation_min_price = $product->get_variation_price();
// If the product category match with the variation 'min" price
if( has_term( $variation_min_price, 'product_cat', $cart_item['product_id'] ) ){
// Cash on delivery (cod) payment gateway
unset($available_gateways['cod']); // unset 'cod'
break; // stop the loop
}
}
}
return $available_gateways;
}
Code goes in functions.php file of your active child theme (or theme) or also in any plugin file.
This should work (but I can't really test it as it's very specific regarding the product categories ID and the min variation prices)…
All related price methods for variable product type:
// All prices: multidimensional array with all variation prices (including active prices, regular prices and sale prices).
$prices = $product->get_variation_prices();
$prices_for_display = $product->get_variation_prices( true ); // For display
// The min or max active price.
$min_price = $product->get_variation_price(); // Min active price
$min_price_for_display = $product->get_variation_price('min', true); // Min active price for display
$max_price = $product->get_variation_price('max'); // Max active price
$max_price_for_display = $product->get_variation_price('max', true); // Max active price for display
// The min or max regular price.
$min_price = $product->get_variation_regular_price(); // Min regular price
$min_price_for_display = $product->get_variation_regular_price('min', true); // Min regular price for display
$max_price = $product->get_variation_regular_price('max'); // Max regular price
$max_price_for_display = $product->get_variation_regular_price('max', true); // Max regular price for display
// The min or max sale price.
$min_price = $product->get_variation_sale_price(); // Min sale price
$min_price_for_display = $product->get_variation_sale_price('min', true); // Min sale price for display
$max_price = $product->get_variation_sale_price('max'); // Max sale price
$max_price_for_display = $product->get_variation_sale_price('max', true); // Max sale price for display
Related answers:
Disable WooCommerce Payment methods if cart item quantity limit is reached
I think you are looking for that :
add_filter( 'woocommerce_variable_sale_price_html', 'get_min_variation_price_format', 10, 2 );
add_filter( 'woocommerce_variable_price_html', 'get_min_variation_price_format', 10, 2 );
function get_min_variation_price_format( $price, $product ) {
$min_variation_price = $product->get_variation_regular_price( 'min');
return wc_price($min_variation_price);
}
Related
I'm trying to edit the backorder notification on the cart page in WooCommerce so that the number of backorders show for each cart item (I'm using variations).
So if a cart item has a quantity of 7 but the stock is 5, the backorder should be 2. (This information is shown on order emails by default in Woocommerce but not on the cart page before the order is made).
The code below works as long as there is only 1 cart item in the cart. But if there is more than 1 cart item, the same number of backorders is returned for all cart items with backorders.
Does anyone know what I should change so that the backorder notification will display the correct number of backorders for each individual cart item that has backorders - no matter how many cart items with backorders there are in the cart?
I'm using the filter hook woocommerce_cart_item_backorder_notification
function backorder_info() {
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// Get an instance of the WC_Product Object
$product = $cart_item['data'];
// Get stock quantity
$stock_qty = $product->get_stock_quantity();
// get cart item quantity
$item_qty = $cart_item['quantity'];
// Calculate number of backorders
$backorder_qty = $item_qty - $stock_qty;
$html = '<p class="backorder_notification">' .__( " " .$backorder_qty. " i restordre","woocommerce").'</p>';
// return backorder quantity
return $html;
}
}
// Display backorder notification on cart page
add_filter( 'woocommerce_cart_item_backorder_notification', 'custom_cart_item_backorder_notification', 10, 2 );
function custom_cart_item_backorder_notification($html, $product_id) {
$html = backorder_info();
return $html;
}
As you can see the woocommerce_cart_item_backorder_notification filter hook contains the productID as the second argument.
Only this is the parentID, and therefore not so easy to determine for variable products which variant (variantID) is currently in cart.
That is why we are going to first ensure through the following code that not the parentID but the real productID is passed to the woocommerce_cart_item_backorder_notification filter hook
function filter_woocommerce_cart_item_product_id( $cart_item_product_id, $cart_item, $cart_item_key ) {
// Return real product ID instead of parent ID
$cart_item_product_id = $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id'];
return $cart_item_product_id;
}
add_filter( 'woocommerce_cart_item_product_id', 'filter_woocommerce_cart_item_product_id', 10, 3 );
And then you get, to change the backorder_notification based on number of backorders
function custom_cart_item_backorder_notification( $html, $product_id ) {
// Get cart items quantities
$cart_item_quantities = WC()->cart->get_cart_item_quantities();
// Product quantity in cart
$product_qty_in_cart = isset( $cart_item_quantities[ $product_id ] ) ? $cart_item_quantities[ $product_id ] : 0;
// Get product
$product = wc_get_product( $product_id );
// Get stock quantity
$stock_qty = $product->get_stock_quantity();
// Still in stock
if ( $stock_qty >= 1 ) {
// Calculate number of backorders
$backorder_qty = $product_qty_in_cart - $stock_qty;
} else {
// Calculate number of backorders
$backorder_qty = $product_qty_in_cart;
}
// Output
$html = '<p class="backorder_notification">' . sprintf( __( '%s in backorder', 'woocommerce' ), $backorder_qty ) . '</p>';
return $html;
}
add_filter( 'woocommerce_cart_item_backorder_notification', 'custom_cart_item_backorder_notification', 10, 2 );
What I'm doing:
I am creating a coupon based promo. The coupon will discount 10% of the most expensive item in the cart that belongs to a specific product category.
The problem:
The code below successfully checks if the cart contains products from the specific category, and obtains 10% of the price of the most expensive product from that array to use for the discount. However, I can't get the coupon discount amount to change in the cart.
The code:
function change_coupon_price_for_promo( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ){
return;
}
// coupon code
$coupon_name = 'MYCOUPONNAME';
// if coupon is applied to cart...
if( $cart->has_discount( $coupon_name ) ) {
// Form array of products from the cart that belong to the specified category
$specProduct = array(); // array of specific products in cart
foreach ( $cart->get_cart() as $key => $cart_item ) {
$cart_item_id = $cart_item['product_id'];
$terms = wp_get_post_terms( $cart_item_id, 'product_cat' );
foreach ( $terms as $term ){
// gets product cat id
$product_cat_id = $term->term_id;
// gets an array of all parent category levels
$product_parent_categories_all_hierachy = get_ancestors( $product_cat_id, 'product_cat' );
// This cuts the array and extracts the last set in the array
$last_parent_cat = array_slice($product_parent_categories_all_hierachy, -1, 1, true);
if(in_array(3831, $last_parent_cat)){
$specProduct[$key] = $cart_item_id;
break;
}
}
}
//if there are items from the specific category in the cart
if(!empty($specProduct)){
$specPriceArray = array(); // array of specific product prices in cart
foreach ($specProduct as $key => $specItem) {
$thisProd = wc_get_product($specItem);
$thisPrice = $thisProd->get_price();
$specPriceArray[$key] = $thisPrice;
}
// most expensive specific product price
$highestSpec = max($specPriceArray);
// discount of most expensive item
$finalDiscount = $highestSpec * .1;
// print_r($specProduct); GOOD
// print_r($specPriceArray); GOOD
// echo $highestSpec; GOOD
// echo $finalDiscount; GOOD
/***** APPLY COUPON CHANGE HERE<-------HOW??? *****/
$cart->discount_total = $finalDiscount;
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'change_coupon_price_for_promo', 10, 1 );
What I'm asking:
The last line of the code before the closing brackets...
$cart->discount_total = $finalDiscount;
is what I tried using to change the coupon's discount in the cart. It doesn't work. How can I accomplish this? TY.
EDIT:
I should note that the coupon being added is set up as a "Fixed cart discount" with a rate of 0 so it is added as a line item to the order. This way the user sees the discount for the coupon code on its own line in the cart/checkout.
you can use function set_price.
you can call it in your code like:
$cart_item['data']->set_price('New price here')
use this inside the foreach that loops your cart items
My WP site sells customized t-shirts. The customization plugin makes each customized shirt a line item in the woocommerce cart. If there are 2 shirts ordered of one design (quantity of 2 on that line item) I want to discount. But if there is just 1 item per line I dont want to discount.
I found this solution
Adding a discount by cart items conditionally based on the item quantity
But this seems to change the product price in the db, so after the discount kicks in for say 2 blue shirts because there were 2 ordered on 1 line, if I add a 3rd shirt on a separate line it also gets the discount, which I dont want.
Since woocommerce version 3+ the linked answer code doesn't work. It needs something different and can even be done in a better way.
The code will apply a cart item discount based on the cart item quantity. In this code example, it will apply a discount of 5% on the cart item, when the quatity is equal or more than 2 (two).
The cart item unit price displayed is always the real product price. The discount will be effective and displayed on the cart item subtotal.
Additionally the product name will be appended with a discount mention.
The code:
add_filter('woocommerce_add_cart_item_data', 'add_items_default_price_as_custom_data', 20, 3 );
function add_items_default_price_as_custom_data( $cart_item_data, $product_id, $variation_id ){
$product_id = $variation_id > 0 ? $variation_id : $product_id;
## ----- YOUR SETTING ----- ##
$discount_percentage = 5; // Discount (5%)
// The WC_Product Object
$product = wc_get_product($product_id);
// Only for non on sale products
if( ! $product->is_on_sale() ){
$price = (float) $product->get_price();
// Set the Product default base price as custom cart item data
$cart_item_data['base_price'] = $price;
// Set the Product discounted price as custom cart item data
$cart_item_data['new_price'] = $price * (100 - $discount_percentage) / 100;
// Set the percentage as custom cart item data
$cart_item_data['percentage'] = $discount_percentage;
}
return $cart_item_data;
}
// Display the product original price
add_filter('woocommerce_cart_item_price', 'display_cart_items_default_price', 20, 3 );
function display_cart_items_default_price( $product_price, $cart_item, $cart_item_key ){
if( isset($cart_item['base_price']) ) {
$product = $cart_item['data'];
$product_price = wc_price( wc_get_price_to_display( $product, array( 'price' => $cart_item['base_price'] ) ) );
}
return $product_price;
}
// Display the product name with the discount percentage
add_filter( 'woocommerce_cart_item_name', 'append_percetage_to_item_name', 20, 3 );
function append_percetage_to_item_name( $product_name, $cart_item, $cart_item_key ){
if( isset($cart_item['percentage']) && isset($cart_item['base_price']) ) {
if( $cart_item['data']->get_price() != $cart_item['base_price'] )
$product_name .= ' <em>(' . $cart_item['percentage'] . '% discounted)</em>';
}
return $product_name;
}
add_action( 'woocommerce_before_calculate_totals', 'custom_discounted_cart_item_price', 20, 1 );
function custom_discounted_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
## ----- YOUR SETTING ----- ##
$targeted_qty = 2; // Targeted quantity
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// For item quantity of 2 or more
if( $cart_item['quantity'] >= $targeted_qty && isset($cart_item['new_price']) ){
// Set cart item discounted price
$cart_item['data']->set_price($cart_item['new_price']);
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
To display the discounted product price instead of the original product price, just remove woocommerce_cart_item_price() function (and hook)…
Newest similar: Cart item quantity progressive percentage discount in Woocommerce 3
I am trying to send out a maximum of 3 free samples to customers with free shipping.
I have created some 0 priced product and set them in "samples" product category.
This specific products have option "sold individually" so customers can only have one of each sample.
I cannot figure out how to allow only a maximum of 3 samples products from this product category on cart.
Any help is appreciated.
This can be done easily using woocommerce_add_to_cart_validation action hook to limit customers to a maximum of 3 items from "sample" product category, this way:
add_action('woocommerce_add_to_cart_validation', 'max_3_items_for_samples', 20, 3 );
function max_3_items_for_samples( $passed, $product_id, $quantity ) {
// HERE define your product category ID, slug or name.
$category = 'clothing';
$limit = 3; // HERE set your limit
$count = 0;
// Loop through cart items checking for specific product categories
foreach ( WC()->cart->get_cart() as $cat_item ) {
if( has_term( $category, 'product_cat', $cat_item['product_id'] ) )
$count++;
}
if( has_term( $category, 'product_cat', $product_id ) && $count == $limit )
$count++;
// Total item count for the defined product category is more than 3
if( $count > $limit ){
// HERE set the text for the custom notice
$notice = __('Sorry, you can not add to cart more than 3 free samples.', 'woocommerce');
// Display a custom notice
wc_add_notice( $notice, 'error' );
// Avoid adding to cart
$passed = false;
}
return $passed;
}
Code goes in function.php file of your active child theme (or theme).
Tested and works.
The above solution does not work. 1) It allows you to initially add more than the limit the first time the product is added. I believe this is because the validation comes before the items are added to the cart, yet the function above loops through items that are already in the cart and 2) it lets the user enter as many of a product that they want, on the the /cart/ page because the woocommerce_update_cart_validation filter is not used.
In WooCommerce, I would like to make a discount without using coupons, and the discount calculation will be based on product price, with something like "take 3 products for the price of 2.
In function.php of my active theme I am using this code:
function promo () {
if (is_cart()) {
$woocommerce->cart->add_fee( __('des', 'woocommerce'), -50.00`enter code here`, true, '');
}
}
add_action ('woocommerce_cart_calculate_fees', 'promo');
My problem: This code doesn't work on checkout page.
If I force in review-order the discount appears, but the total value don't change. I think its not saving the fee.
How can I make it work (on checkout page)?
Thanks
This hook is made for cart fees (or discounts), so you have to remove if (is_cart()) { condition, that why it's not working…
Here is the correct functional code to achieve a "Buy 2 take 3" discount, that will make a discount based on line item quantity:
add_action('woocommerce_cart_calculate_fees' , 'discount_2_for_3', 10, 1);
function discount_2_for_3( $cart_object ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Initialising variable
$discount = 0;
// Iterating through cart items
foreach( $cart_object->get_cart() as $cart_item ){
// Getting item data from cart object
$item_id = $cart_item['product_id']; // Item Id or product ID
$item_qty = $cart_item['quantity']; // Item Quantity
$product_price = $cart_item['data']->price; // Product price
$line_total = $cart_item['line_total']; // Price x Quantity total line item
// THE DISCOUNT CALCULATION
if($item_qty >= 3){
// For each item quantity step of 3 we add 1 to $qty_discount
for($qty_x3 = 3, $qty_discount = 0; $qty_x3 <= $item_qty; $qty_x3 += 3, $qty_discount++);
$discount -= $qty_discount * $product_price;
}
}
// Applied discount "2 for 3"
if( $discount != 0 ){
// Note: Last argument is related to applying the tax (false by default)
$cart_object->add_fee( __('Des 2 for 3', 'woocommerce'), $discount, false);
}
}
This will work for simple products, but not for product variations…
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Code is tested and works.