In WooCommerce I would like to exclude certain products in the shopping cart from calculating the shipping cost, based on certain conditions. After trying various ways an Googling for hours, I can't find any way to calculate the shipping cost only over the remaining products.
The webshop uses many shipping classes for various types of product. The shipping cost for the various classes are being add up. When a certain amount of specific products is ordered, those products will be shipped for free, but for the other products in the cart the shipping cost still need to be calculated, even if they belong to the same shipping class as the product that is shipped for free.
What I tried
My first idea was to use the woocommerce_package_rates filter and remove the shipping cost of the matching products. But that turned out to be very complex, as I could not calculate the actual shipping cost for those products. Additionally, there might be other products in the cart available with the same shipping class.
Then I thought the solution might be to update the shipping class for the product instance in the cart to a Free Shipping class, using the set_shipping_class_id() method on the cart-data after adding an action to the woocommerce_before_calculate_totals hook:
add_action('woocommerce_before_calculate_totals', 'updateShippingClasses', 30, 1);
function updateShippingClasses($rates) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
foreach (WC()->cart->get_cart() as $cart_item) {
if (my_condition) {
$cart_item['data']->set_shipping_class_id(1947); // The Free Shipping class ID.
}
}
}
It adds the "changed" shipping_class_id value to the object, but it's not used to calculate the shipping cost: the original values still remain.
On the internet I found many similar questions, but every time it was about making the shipping completely free or update the class for the product itself. But in my case, that is not the solution.
I adopted various solutions for these issues, using the above mentioned hooks, as well as the woocommerce_shipping_rate_cost, but with none of them I achieved what I am looking for.
Is there any way to programmatically exclude some products from calculating the shipping cost, but still calculate the shipping cost of the remaining products in the cart?