I need modify cost of shipping options depending on what is inside my cart/order.
The cost must be calculated on cart page and checkout page and of course save when order completed.
This is what I've done but it seems it has no effect, could someone has an idea please ?
add_filter('woocommerce_package_rates','over_cost',100,2);
function over_cost($rates,$package) {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$qty=0;
foreach($items as $item => $values) {
$_product = $values['data']->post;
$qty= $qty + $values['quantity'];
}
foreach ($rates as $rate) {
if ($rate->cost=='flat_rate:4') {$rate->cost = 5*$qty;}
}
return $rates;
}
add_filter('woocommerce_package_rates','test_overwrite_fedex',100,2);
function test_overwrite_fedex($rates,$package) {
foreach ($rates as $rate) {
//Set the price
$rate->cost = 1000;
//Set the TAX
$rate->taxes[1] = 1000 * 0.2;
}
return $rates;
}
The rates are cached by Woocommerce using the wordpress transient function. So when you're testing, make sure you change the item quantity so the package rates are updated correctly, or you can empty the cart each time you refresh:)
Related
If a woocommerce cart has a virtual item only it does not show shipping methods.
I have a unique situation where I'd like this to be the case also if the cart contains physical products but at least one virtual product (ie any virtual product in the cart, regardless of whatever else is in the cart, hide shipping methods). Whereas if no virtual products are in the cart then show shipping methods as normal.
I've tried the code below but it doesn't seem to work:
Thanks for your help
add_filter( 'woocommerce_cart_needs_shipping_address', 'filter_cart_needs_shipping_address_callback' );
function filter_cart_needs_shipping_address_callback( $needs_shipping_address ){
// Loop through cart items
foreach ( WC()->cart->get_cart() as $item ) {
if ( $item['data']->is_virtual() ) {
$needs_shipping_address = false;
break; // Stop the loop
}
}
return $needs_shipping_address;
}
Thanks, it was throwing the error "Uncaught Error: Call to a member function get_cart() on null" but have managed to fix it with this:
if ( is_null( WC()->cart ) ) {
wc_load_cart();
} else
Let me know if there is a better way to do it? Thanks
add_filter( 'woocommerce_cart_needs_shipping', 'filter_cart_needs_shipping_address_callback' );
function filter_cart_needs_shipping_address_callback( $needs_shipping ){
// Loop through cart items
if ( is_null( WC()->cart ) ) {
wc_load_cart();
} else {
foreach ( WC()->cart->get_cart() as $item ) {
if ( $item['data']->is_virtual() ) {
$needs_shipping = false;
break; // Stop the loop
}
}
return $needs_shipping;
}
}
I think I figured out how to do it for you.
The Hook you're using in your example is not the right one since it's just filtering the shipping address callback.
What I think you need to do is use the woocommerce cart needs shipping hook.
Since it was throwing an error you could try to only run the code on the cart and checkout page. You can do that by using if ( is_cart() || is_checkout() ) {
Try the edited code below and let me know how it works.
Have a wonderful day!
add_filter( 'woocommerce_cart_needs_shipping', 'remove_virtual_product_shipping_methods' );
function remove_virtual_product_shipping_methods( $needs_shipping ){
//Only execute code on cart and checkout page.
if ( is_cart() || is_checkout() ) {
//Loop trough cart items
foreach ( WC()->cart->get_cart() as $item ) {
//If a product in cart is a vritual product remove all shipping
if ( $item['data']->is_virtual() ) {
$needs_shipping = false;
break;
}
}
return $needs_shipping;
}
}
I am trying to discount the cheapest item in the cart if my coupon type is used:
add_filter('woocommerce_coupon_get_discount_amount', 'wc_cpn_disc', 10, 5);
function wc_cpn_disc($discount, $discounting_amount, $cart_item, $single, $coupon) {
// IF TYPE MATCHES PERFORM CUSTOM CALCULATION
if ($coupon->type == 'cheapest_free'){
global $woocommerce;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$product_price[] = get_option('woocommerce_tax_display_cart') == 'excl' ? $_product->get_price_excluding_tax() : $_product->get_price_including_tax(); /*Store all product price from cart items in Array */
}
$lowestprice = min($product_price);
$discount = number_format((float)$lowestprice/10,2,'.','');
}
return $discount;
}
The discount amount is very weird - no matter what I try, it never comes out to the value I expect. At first I thought it was a percentage discount, but I expect this to be a fixed amount. I have tried running my get lowest price bit of function elsewhere on the site and it returns 1.195 when the lowest value item is 11.95 - so I know that part works. But the discount on a total basket of 265.60 is 23.90 - I just don't get it!
I just want to get the lowest priced item in the cart, and discount that amount.
I managed to solve this with the help of Bossman and a couple of other threads. It turns out I needed to change my method - full code below.
add_filter('woocommerce_coupon_get_discount_amount', 'tfcc_cheapest_free', 10, 5);
function tfcc_cheapest_free($discount, $discounting_amount, $cart_item, $single, $coupon) {
// IF TYPE MATCHES PERFORM CUSTOM CALCULATION
if ($coupon->type == 'cheapest_free'){
$items_prices = [];
$items_count = 0;
// Loop through cart items
foreach( WC()->cart->get_cart() as $key => $item ){
// Get the cart item price (the product price)
if ( wc_prices_include_tax() ) {
$price = wc_get_price_including_tax( $item['data'] );
} else {
$price = wc_get_price_excluding_tax( $item['data'] );
}
if ( $price > 0 ){
$items_prices[$key] = $price;
$items_count += $item['quantity'];
}
}
// Only when there is more than one item in cart
if ( $items_count > 1 ) {
asort($items_prices); // Sorting prices from lowest to highest
$item_keys = array_keys($items_prices);
$item_key = reset($item_keys); // Get current cart item key
// Targeting only the current cart item that has the lowest price
if ( $cart_item['key'] == $item_key ) {
return reset($items_prices)/$cart_item['quantity']; // return the lowest item price as a discount
}
} else {
return 0;
}
}
}
I hope this might help someone else out who needs a similar feature in the future.
Hi all :) I understand that there are a lot of such topics, but, unfortunately, I cannot apply any code, and I do not know how to redo and apply it.
I added an additional shipping method for specific countries using the Innozilla Per Product Shipping WooCommerce plugin for a specific product
when selecting a specific country, I see old shipping methods like flexible_shipping_9_2, flat_rate: 12 and + new "per_product" shipping method
I would like to hide all delivery methods except per_product when the per_product delivery method is used.
How to do it? Thank you in advance.
add_filter( 'woocommerce_package_rates', 'businessbloomer_hide_free_shipping_for_shipping_class', 10, 2 );
function businessbloomer_hide_free_shipping_for_shipping_class( $rates, $package ) {
$shipping_class_target = 15; // shipping class ID
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target ) {
$in_cart = true;
break;
}
}
if ( $in_cart ) {
unset( $rates['free_shipping:8'] ); // shipping method with ID
}
return $rates;
}
In functions.php of my child theme I have custom script like this:
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process1');
function my_custom_checkout_field_process1() {
//do something
}
To do some calculations I need to get the cost of chosen shipping method. How to do that?
I got it!
$cart = WC()->cart;
$total = __( 'Free!', 'woocommerce' );
if ( 0 < $cart->get_shipping_total() ) {
if ( $cart->display_prices_including_tax() ) {
$total = $cart->shipping_total + $cart->shipping_tax_total;
} else {
$total = $cart->shipping_total;
}
}
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