I am trying to get the shipping class associated with each line item for both simple and variable products, then find out which one has the highest cost and charge that only removing the rest of the shipping cost. It's for WooCommerce.
What I did-
Edit: code so far added.
add_filter('woocommerce_package_rates', 'custom_shipping_method_by_class', 10, 2);
function custom_shipping_method_by_class($rates, $package)
{
$class_costs = array();
foreach ($package['contents'] as $item) {
$product_id = $item['product_id'];
$product = wc_get_product($product_id);
if ($product instanceof WC_Product_Variable) {
foreach ($product->get_visible_children() as $variation_id) {
$term = wp_get_post_terms($variation_id, 'product_shipping_class');
if (!empty($term)) {
$term = reset($term);
$class_costs[$term->term_id] = max($class_costs[$term->term_id] ?? 0, $rates["{$term->term_id}:$variation_id"]->cost);
var_dump($class_costs); // I get 0 here although I the variation has the shipping class set and the class has an amount set too.
}
}
} else {
$term = wp_get_post_terms($product_id, 'product_shipping_class');
if (!empty($term)) {
$term = reset($term);
$class_costs[$term->term_id] = max($class_costs[$term->term_id] ?? 0, $rates["{$term->term_id}:$product_id"]->cost);
}
}
}
foreach ($rates as $rate_key => $rate) {
list($class_id, $product_id) = explode(':', $rate_key);
if (!array_key_exists($class_id, $class_costs) || $class_costs[$class_id] !== $rate->cost) {
unset($rates[$rate_key]);
}
}
return $rates;
}
You don't need any code as there is "Calculation type" setting option (select field) on each Flat rate, where you can select between "Per class: Charge shipping for each shipping class individually" or "Per order: Charge shipping for the most expensive shipping class":