php - Use different different shipping prices based on cart subtotal in Woocommerce

Solution:
Try the following function which "Flat Rate" cost will be changed based on cart subtotal as defined in your question.
If cart subtotal is up to 5000, we will hide "Flat Rate". You will need to enable free shipping method with "A minimum order amount" option of 5000.
Using "Flate rate" shipping method, you will need to set a reference shipping cost with a simple initial cost instead of any formula. It can be for example1
. This cost will be replaced by my answer code, dynamically based on cart total weight.
It will handle also a specific product ID and will set the cost to 500 if is in cart.
You may have to "Enable debug mode" in general shipping settings under "Shipping options" tab, to disable temporarily shipping caches.
The code:
add_filter('woocommerce_package_rates', 'shipping_cost_based_on_price', 12, 2);
function shipping_cost_based_on_price( $rates, $package ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return $rates;
// HERE define the differents costs
$cost1 = 150; // Below 2000
$cost2 = 250; // Below 5000
$cost3 = 500; // Cost for our specific product ID
$step1_subtotal = 2000;
$max_subtotal = 5000;
// HERE DEFINE the specific product ID to be charged at 500
$targeted_product_id = 37;
// The cart subtotal
$subtotal = WC()->cart->get_subtotal();
// Loop through cart items and checking for the specific product
$found = false;
foreach( $package['contents'] as $item ) {
if( $item['product_id'] == $targeted_product_id || $item['variation_id'] == $targeted_product_id ){
$found = true;
break;
}
}
// Loop through the shipping taxes array
foreach ( $rates as $rate_key => $rate ){
$has_taxes = false;
// If subtotal is up to 5000 we enable free shipping only
if( 'free_shipping' !== $rate->method_id && $subtotal >= $max_subtotal ){
unset($rates[$rate_key]);
}
// Targetting "flat rate" only for subtotal below 5000
else if( 'flat_rate' === $rate->method_id && $subtotal < $max_subtotal ){
// Get the initial cost
$initial_cost = $new_cost = $rates[$rate_key]->cost;
// Calculate new cost
if( $subtotal < $step1_subtotal ) { // Below 2000
$new_cost = $cost1;
}
elseif( $subtotal >= $step1_subtotal && $subtotal < $max_subtotal ) { // Between 2000 and below 5000
$new_cost = $cost2;
}
// For the specific product ID (if found in cart items)
if( $found ){
$new_cost = $cost2;
}
// Set the new cost
$rates[$rate_key]->cost = $new_cost;
// Taxes rate cost (if enabled)
$taxes = [];
// Loop through the shipping taxes array (as they can be many)
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $rates[$rate_key]->taxes[$key] > 0 ){
// Get the initial tax cost
$initial_tax_cost = $new_tax_cost = $rates[$rate_key]->taxes[$key];
// Get the tax rate conversion
$tax_rate = $initial_tax_cost / $initial_cost;
// Set the new tax cost
$taxes[$key] = $new_cost * $tax_rate;
$has_taxes = true; // Enabling tax
}
}
if( $has_taxes )
$rates[$rate_key]->taxes = $taxes;
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Once tested, don't forget to disable "Enable debug mode" option in shipping settings.
Share solution ↓
Additional Information:
Link To Answer People are also looking for solutions of the problem: script cache:clear returned with error code 255
Didn't find the answer?
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Similar questions
Find the answer in similar questions on our website.
Write quick answer
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.