Search code examples
phpwoocommerceadvanced-custom-fieldscart

Passing value from function to woocommerce hook


In Woocommerce I'm trying to pass some value from a custom simple function to a hooked function in "woocommerce_before_calculate_totals" action hook. But I get always an empty value.

I tried to dump the $new_price in add_custom_item_price() function and its still int(0).
I also tried to dump $_POST['fabric_length'] in add_custom_item_price() function and its NULL.

This is my code:

function calculate_new_price() {
    global $post;

    $category = wp_get_post_terms($post->ID,'product_cat');
    $meter_price = get_field('meter_price');
    $price_per_centimeter = $meter_price / 100;
    $total_height_price = $_POST['fabric_length'] * $price_per_centimeter;

    return $total_height_price;
}

$new_price = calculate_new_price();

add_filter( 'woocommerce_before_calculate_totals', 'add_custom_item_price', 10, 1 );
function add_custom_item_price( $cart_object ) {
    global $new_price; <------ returns int(0) when var_dump in this function

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    foreach (  $cart_object->get_cart() as $item_values ) {
        $item_values['data']->set_price(ceil($new_price));
    }
}

What am I missing?

Any help is appreciated.


Solution

  • Update…

    Here is a complete code (verifiable), with frontend and backend custom fields that will show you the correct way to make it work on advanced customizations without the need of using Advanced custom fields:

    // Frontend: The product custom field [FOR TESTING]
    add_action( 'woocommerce_before_add_to_cart_button', 'fabric_length_product_field' );
    function fabric_length_product_field() {
        global $product;
        // The fake calculated price
        ?>
            <div>
                <label class="product-custom-text-label" for="servicetime"><?php _e( 'Fabric lenght:', 'woocommerce'); ?><br>
                    <input type="text" id="fabric_length" name="fabric_length" value="">
                </label>
            </div><br>
        <?php
    }
    
    // Backend: Add a custom field to product in backend [FOR TESTING]
    add_action( 'woocommerce_product_options_pricing', 'add_field_product_options_pricing' );
    function add_field_product_options_pricing() {
        global $post;
    
        echo '<div class="options_group">';
    
        woocommerce_wp_text_input( array(
            'id'            => '_meter_price',
            'label'         => __('Metter price', 'woocommerce') . ' (' . get_woocommerce_currency_symbol() . ')',
            'placeholder'   => __('Set the Metter price…', 'woocommerce'),
            'description'   => __('Enter the custom value here.', 'woocommerce'),
            'desc_tip'      => 'true',
        ));
    
        echo '</div>';
    }
    
    // Save product custom field to database when submitted in Backend [FOR TESTING]
    add_action( 'woocommerce_process_product_meta', 'save_product_options_custom_fields', 30, 1 );
    function save_product_options_custom_fields( $post_id ){
        // Saving custom field value
        if( isset( $_POST['_meter_price'] ) ){
            update_post_meta( $post_id, '_meter_price', sanitize_text_field( $_POST['_meter_price'] ) );
        }
    }
    
    // Add custom calculated price conditionally as custom data to cart items
    add_filter( 'woocommerce_add_cart_item_data', 'add_custom_price_to_cart_item_data', 20, 2 );
    function add_custom_price_to_cart_item_data( $cart_item_data, $product_id ){
        if( ! isset($_POST['fabric_length']) )
            return $cart_item_data;
    
        // Get your data
        $meter_price = get_post_meta( $product_id, '_meter_price', true );
        if( empty($meter_price) || $meter_price == 0 )
            return $cart_item_data;
    
        $fabric_length = (float) sanitize_text_field( $_POST['fabric_length'] );
        if( empty($fabric_length) || $fabric_length == 0 )
            return $cart_item_data;
    
        // Price Calculations and saving
        $cart_item_data['custom_price'] = ceil( $fabric_length * $meter_price / 100 );
        $cart_item_data['unique_key'] = md5( microtime() . rand() ); // Make each item unique
    
        return $cart_item_data;
    }
    
    // Set conditionally a custom item price
    add_action('woocommerce_before_calculate_totals', 'set_cutom_cart_item_price', 20, 1);
    function set_cutom_cart_item_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_price'] ) )
                $cart_item['data']->set_price( $cart_item['custom_price'] );
        }
    }
    

    enter image description here

    enter image description here

    enter image description here

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