Set a calculated price for variable products in th

2019-05-06 19:59发布

In Woocommerce, I use custom fields to calculate the price of a product, based on this code - Add custom fields to custom product calculated price in Woocommerce. Thanks for the help LoicTheAztec.

// Add a custom field before single add to cart
add_action( 'woocommerce_before_add_to_cart_button', 'custom_product_price_field', 5 );
function custom_product_price_field(){
echo '<div class="custom-text text">
<h3>Rental</h3>
<label>Start Date:</label>
<input type="date" name="rental_date" value="" class="rental_date" />
<label>Period Rental:</label>
<select name="custom_price" class="custom_price">
    <option value="30" selected="selected">2 days</option>
    <option value="35">4 days</option> 
</select>
</div>';
}

// Get custom field value, calculate new item price, save it as custom cart item data
add_filter('woocommerce_add_cart_item_data', 'add_custom_field_data', 20, 2 );
function add_custom_field_data( $cart_item_data, $product_id ){
if ( isset($_POST['rental_date']) && ! empty($_POST['rental_date']) ){
    $cart_item_data['custom_data']['date'] = $_POST['rental_date'];
}
if ( isset($_POST['custom_price']) && ! empty($_POST['custom_price']) ){
    $product      = wc_get_product($product_id); // The WC_Product Object
    $base_price   = (float) $product->get_regular_price(); // Product reg price
    $custom_price = (float) sanitize_text_field( $_POST['custom_price'] );

    $cart_item_data['custom_data']['base_price'] = $base_price;
    $cart_item_data['custom_data']['new_price'] = $base_price * $custom_price/100;
    $cart_item_data['custom_data']['rental'] = $custom_price;
}
if ( isset($cart_item_data['custom_data']['new_price']) || isset($cart_item_data['custom_data']['date']) ){
    $cart_item_data['custom_data']['unique_key'] = md5( microtime() . rand() ); // Make each item unique
}
return $cart_item_data;
}

// Set the new calculated cart item price
add_action( 'woocommerce_before_calculate_totals', 'extra_price_add_custom_price', 20, 1 );
function extra_price_add_custom_price( $cart ) {
if ( is_admin() && !defined('DOING_AJAX') )
    return;

foreach ( $cart->get_cart() as $cart_item ) {
    if( isset($cart_item['custom_data']['new_price']) )
        $cart_item['data']->set_price( (float) $cart_item['custom_data']['new_price'] );
}
}

// Display cart item custom price details
add_filter('woocommerce_cart_item_price', 'display_cart_items_custom_price_details', 20, 3 );
function display_cart_items_custom_price_details( $product_price, $cart_item, $cart_item_key ){
if( isset($cart_item['custom_data']['new_price']) ) {
    $product        = $cart_item['data'];
    $new_price     = $cart_item['custom_data']['new_price'];
    $product_price  = wc_price( wc_get_price_to_display( $product, array( 'price' => $new_price ) ) ) . '<br>';
    if( isset($cart_item['custom_data']['rental']) ) {
        $product_price .= $cart_item['custom_data']['rental'] == '30' ? __("2 days") : __("4 days");
    }
}
return $product_price;
}

// Display in cart item the selected date
add_filter( 'woocommerce_get_item_data', 'display_custom_item_data', 10, 2 );
function display_custom_item_data( $cart_item_data, $cart_item ) {
if ( isset( $cart_item['custom_data']['date'] ) ){

    $cart_item_data[] = array(
        'name' => __("Chosen date", "woocommerce" ),
        'value' =>   date('d.m.Y', strtotime($cart_item['custom_data']['date'])),
    );
}
if ( isset( $cart_item['custom_data']['rental'] ) ){
    $cart_item_data[] = array(
        'name' => __("Period Rental", "woocommerce" ),
        'value' =>   $cart_item['custom_data']['rental'] == '30' ? __("2 days") : __("4 days"),         
    );
}
return $cart_item_data;
}

I decided to create a new question, because I think it is appropriate in this case.

All the code is completely working, but there is a problem. This code works for simple products, and I have a lot of variational products.

enter image description here

This code does not show the price of variational products. It shows only the date and the period.

enter image description here

How to solve this problem? Any thoughts?

1条回答
三岁会撩人
2楼-- · 2019-05-06 20:49

Updated

In your code, you need to change woocommerce_add_cart_item_data() function, to handle product variations.

There is other some other arguments that can be used as $variation_id in this hook.

The code:

// Add a custom field before single add to cart
add_action( 'woocommerce_before_add_to_cart_button', 'custom_product_price_field', 5 );
function custom_product_price_field(){
    echo '<div class="custom-text text">
    <h3>Rental</h3>
    <label>Start Date:</label>
    <input type="date" name="rental_date" value="" class="rental_date" />
    <label>Period Rental:</label>
    <select name="custom_price" class="custom_price">
        <option value="30" selected="selected">2 days</option>
        <option value="35">4 days</option>
    </select>
    </div>';
}

// Get custom field value, calculate new item price, save it as custom cart item data
add_filter('woocommerce_add_cart_item_data', 'add_custom_field_data', 20, 3 );
function add_custom_field_data( $cart_item_data, $product_id, $variation_id ){
    if ( isset($_POST['rental_date']) && ! empty($_POST['rental_date']) ){
        $cart_item_data['custom_data']['date'] = $_POST['rental_date'];
    }
    if ( isset($_POST['custom_price']) && ! empty($_POST['custom_price']) ){
        $_product_id = $variation_id > 0 ? $variation_id : $product_id;
        $product      = wc_get_product($_product_id); // The WC_Product Object
        $base_price   = (float) $product->get_regular_price(); // Product reg price
        $custom_price = (float) sanitize_text_field( $_POST['custom_price'] );

        $cart_item_data['custom_data']['base_price'] = $base_price;
        $cart_item_data['custom_data']['new_price'] = $base_price/100 * $custom_price;
        $cart_item_data['custom_data']['rental'] = $custom_price;
    }
    if ( isset($cart_item_data['custom_data']['new_price']) || isset($cart_item_data['custom_data']['date']) ){
        $cart_item_data['custom_data']['unique_key'] = md5( microtime() . rand() ); // Make each item unique
    }
    return $cart_item_data;
}

// Set the new calculated cart item price
add_action( 'woocommerce_before_calculate_totals', 'extra_price_add_custom_price', 20, 1 );
function extra_price_add_custom_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    foreach ( $cart->get_cart() as $cart_item ) {
        if( isset($cart_item['custom_data']['new_price']) )
            $cart_item['data']->set_price( (float) $cart_item['custom_data']['new_price'] );
    }
}

// Display cart item custom price details
add_filter('woocommerce_cart_item_price', 'display_cart_items_custom_price_details', 20, 3 );
function display_cart_items_custom_price_details( $product_price, $cart_item, $cart_item_key ){
    if( isset($cart_item['custom_data']['base_price']) ) {
        $product        = $cart_item['data'];
        $base_price     = $cart_item['custom_data']['base_price'];
        $product_price  = wc_price( wc_get_price_to_display( $product, array( 'price' => $base_price ) ) ) . '<br>';
        if( isset($cart_item['custom_data']['rental']) ) {
            $product_price .= $cart_item['custom_data']['rental'] == '30' ? __("2 days") : __("4 days");
        }
    }
    return $product_price;
}

// Display in cart item the selected date
add_filter( 'woocommerce_get_item_data', 'display_custom_item_data', 10, 2 );
function display_custom_item_data( $cart_item_data, $cart_item ) {
    if ( isset( $cart_item['custom_data']['date'] ) ){

        $cart_item_data[] = array(
            'name' => __("Chosen date", "woocommerce" ),
            'value' =>   date('d.m.Y', strtotime($cart_item['custom_data']['date'])),
        );
    }
    if ( isset( $cart_item['custom_data']['rental'] ) ){
        $cart_item_data[] = array(
            'name' => __("Period Rental", "woocommerce" ),
            'value' =>   $cart_item['custom_data']['rental'] == '30' ? __("2 days") : __("4 days"),
        );
    }
    return $cart_item_data;
}

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

enter image description here

查看更多
登录 后发表回答