2
votes

Based on WooCommerce modify cart totals programmatically, im trying to get cart meta inside the 'woocommerce_cart_product_subtotal' filter hook, but I'm stuck. I've tried $a_variable = $cart_item['length']; , but it doesn't work.

Here's my code:

add_filter( 'woocommerce_cart_product_subtotal', 'filter_woocommerce_cart_product_subtotal', 10, 6); 
function filter_woocommerce_cart_product_subtotal( $product_subtotal, $product, $quantity, $instance) { 

$prisen = $product->get_price();
$rope_length =$cart_item['length'];
$product_subtotal = ($prisen*$rope_length)*$quantity;
return $product_subtotal; 
}; 

Does anyone have any ideas?

2
Where is $cart_item defined ?Romain B.
@RomainB. I have no idea. I'm a complete noob when it comes to programming.Paudun
That may be why 'it doesn't work'. You are trying to use a variable that's not set in the scope of your function.Romain B.
I have tried adding it to the scope, but it doesn't work then either.Paudun
Can you print $cart_item and see what is in it?Darsh khakhkhar

2 Answers

2
votes

You are not doing that in the right way and you need to rethink it differently…

Here is a complete example that will allow you to keep the default item price (product price) and to get a calculated cart item subtotal based on your "length" custom cart item data:

// For testing (example): Add a dropdown to product page for lenght
add_action( 'woocommerce_before_add_to_cart_button', 'add_lenght_custom_field');
function add_lenght_custom_field() {
    echo '<div class="class_dropdown_length">
        <label for="rope_length">Select a length</label>
        <select id ="rope_length" name="rope_length">
            <option value="">1 m</option>
            <option value="5">5 m</option>
            <option value="10">10 m</option>
            <option value="25">25 m</option>
        </select>
    </div>';
}

// Add custom cart item data (lenght) on add to cart and calculate the new price
add_filter( 'woocommerce_add_cart_item_data', 'filter_woocommerce_add_cart_item_data', 10, 3 );
function filter_woocommerce_add_cart_item_data( $cart_item_data, $product_id, $variation_id) {
    if( isset($_POST['rope_length']) && ! empty($_POST['rope_length']) ) {
        $the_id  = $variation_id > 0 ? $variation_id : $product_id;

        $product = wc_get_product( $the_id );

        $length  = (float) esc_attr($_POST['rope_length']); // The chosen lenght

        // Add the dropdown value as custom cart item data
        $cart_item_data['custom'] = array(
            'length'     => $length, // The lenght value from custom field (if needed)
            'price'      => $product->get_price(), // The default product price
            'new_price'  => $product->get_price() * $length, // Calculated price from lenght
            'unique_key' => md5(microtime().rand()), // Make each item unique
        );
    }
    return $cart_item_data;
}

// Display the selected lenght value below cart item name
add_filter( 'woocommerce_cart_item_name', 'display_select_length_after_cart_item_name', 10, 3 );
function display_select_length_after_cart_item_name( $name, $cart_item, $cart_item_key ) {
    if( is_cart() && isset($cart_item['custom']['length']) ) {
        $name .= '<p>'.__("Lenght:") . ' ' . esc_html($cart_item['custom']['length']) . '</p>';
    }
    return $name;
}

// Display the default product price (instead of the calculated one)
add_filter( 'woocommerce_cart_item_price', 'filter_woocommerce_cart_item_price', 10, 3 );
function filter_woocommerce_cart_item_price( $product_price, $cart_item, $cart_item_key  ) {
    if( isset($cart_item['custom']['price']) ) {
        $product_price = wc_price( wc_get_price_to_display( $cart_item['data'], array('price' => $cart_item['custom']['price']) ) );
    }
    return $product_price;
}

// Customizing cart item price subtotal
add_action( 'woocommerce_before_calculate_totals', 'set_cart_item_calculated_price', 10, 1 );
function set_cart_item_calculated_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // Required since Woocommerce version 3.2 for cart items properties changes
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // Loop through cart items
    foreach ( $cart->get_cart() as $cart_item ) {
        // Set the new calculated price based on lenght
        if( isset($cart_item['custom']['new_price']) ) {
            $cart_item['data']->set_price( $cart_item['custom']['new_price'] );
        }
    }
}

This code goes in function.php file of your active child theme (or active theme). Tested and works.

You can see that the product price is different that the custom calculated subtotal (price x length):

enter image description here

0
votes
add_filter('woocommerce_cart_product_subtotal', 'filter_woocommerce_cart_product_subtotal', 10, 4);

function filter_woocommerce_cart_product_subtotal($product_subtotal, $product, $quantity, $cart) {

    $newproduct_subtotal = 0;
    $prisen = $product->get_price();
    $rope_length = $product->get_length();
    if ($prisen && $rope_length)
        $newproduct_subtotal += ($prisen * $rope_length) * $quantity;

    return ($newproduct_subtotal) ? wc_price($newproduct_subtotal) : $product_subtotal;
}