Search code examples
phpwordpresswoocommerceproduct

Display custom price based on custom fields for Woocommerce simple product


In Woocommerce, I would like update base price depending on 2 selected custom fields.

With the help of LoicTheAztec I can update price of 1 custom field, so, how do a update 2 custom fields?

PHP code:

add_action( 'woocommerce_before_add_to_cart_button', 'custom_product_field' );
function custom_product_field() {
    global $product;
    if( $product->is_type('variable') ) return; 
    $options = array(
    ""          => __('Tipos'),
    "20.00" => "Tipo 1 + 20,00",
    "25.00" => "Tipo 2 + 25,00",
    );
    woocommerce_form_field('amostra', array(
    'type'          => 'select',
    'class'         => array('my-field-class form-row-wide'),
    'label'         => __('Tipos', $domain),
    'required'      => true,
    'options'       => $options,
    ),'');
    $options_ra = array(
    ""          => __('Sem Modelos'),
    "15.00" => "Modelo A + 15,00",
    "25.00" => "Modelo B + 25,00",
    );
    woocommerce_form_field('amostraB', array(
    'type'          => 'select',
    'class'         => array('my-field-class_ra form-row-wide'),
    'label'         => __('Modelos', $domain),
    'required'      => true,
    'options'       => $options_ra,
    ),'');
    $base_price = (float) wc_get_price_to_display( $product );
    $prices = array(
    ''      => wc_price($base_price),
    '20.00' => wc_price($base_price + 20),
    '25.00' => wc_price($base_price + 25),
    '15.00' => wc_price($base_price + 15),
    '25.00' => wc_price($base_price + 25),
    );
}

JS code:

jQuery(function($){
    var a = <?php echo json_encode($prices); ?>,
        b = 'p.price',
        c = 'select[name="amostra"]';

    $(c).on( 'change', function(){
        $.each( a, function( key, value ){
            if( $(c).val() == key )
                $(b).html(value);
        });
    });
});

Example

Any help please.


Solution

  • This code just handle the displayed price change on single product pages based on custom fields selected values for simple products which price is not on sale.

    This is a bit much more complicated as the 2 select fields can interact on the calculated price at the same time and of because this case, this need to be handled differently.

    The code will not change the cart item price, as more code is needed for that.

    enter image description here

    I have added some custom formatting price functions, to be able to achieve that… Here is the code:

    // Custom formatting price function
    function wc_custom_price( $price, $args = array() ) {
        $args = apply_filters( 'wc_price_args', wp_parse_args( $args, array(
            'ex_tax_label'       => false,
            'currency'           => '',
            'decimal_separator'  => wc_get_price_decimal_separator(),
            'thousand_separator' => wc_get_price_thousand_separator(),
            'decimals'           => wc_get_price_decimals(),
            'price_format'       => get_woocommerce_price_format(),
        ) ) );
    
        $unformatted_price = $price;
        $negative          = $price < 0;
        $price             = apply_filters( 'raw_woocommerce_price', floatval( $negative ? $price * -1 : $price ) );
        $price             = apply_filters( 'formatted_woocommerce_price', number_format( $price, $args['decimals'], $args['decimal_separator'], $args['thousand_separator'] ), $price, $args['decimals'], $args['decimal_separator'], $args['thousand_separator'] );
    
        if ( apply_filters( 'woocommerce_price_trim_zeros', false ) && $args['decimals'] > 0 ) {
            $price = wc_trim_zeros( $price );
        }
    
        $formatted_price = ( $negative ? '-' : '' ) . sprintf( $args['price_format'], '<span class="woocommerce-Price-currencySymbol">' . get_woocommerce_currency_symbol( $args['currency'] ) . '</span>', '<span class="numeric-price">' . $price . '</span>' );
        $return          = '<span class="woocommerce-Price-amount amount">' . $formatted_price . '</span>';
    
        if ( $args['ex_tax_label'] && wc_tax_enabled() ) {
            $return .= ' <small class="woocommerce-Price-taxLabel tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
        }
        return apply_filters( 'wc_price', $return, $price, $args, $unformatted_price );
    }
    
    // Custom formated product price on single product pages for simple products
    add_filter( 'woocommerce_get_price_html', 'custom_get_price_html', 10, 2 );
    function custom_get_price_html( $price, $product ) {
        if( '' === $product->get_price() || $product->is_on_sale() ) {
            return $price;
        } elseif ( is_product() && $product->is_type('simple') ) {
            $price = wc_custom_price( wc_get_price_to_display( $product ) ) . $product->get_price_suffix();
        }
        return $price;
    }
    
    // Displaying selected custom fields calculated product price on single product pages for simple products
    add_action( 'woocommerce_before_add_to_cart_button', 'simple_product_price_custom_fields' );
    function simple_product_price_custom_fields() {
        global $product;
    
        // Not for variable products and Not for products on sale
        if( ! $product->is_type('simple') || $product->is_on_sale() )
            return;
    
        $domain = 'woocommerce';
    
        woocommerce_form_field('amostra', array(
            'type'     => 'select',
            'class'    => array('my-field-class form-row-wide'),
            'label'    => __('Tipos', $domain),
            'required' => true,
            'options'  => array(
                ''      => __('Sem Tipos', $domain),
                '20.00' => __('Tipo 1 + 20,00', $domain),
                '25.00' => __('Tipo 2 + 25,00', $domain),
            )
        ), '' );
    
        woocommerce_form_field('amostra_ra', array(
            'type'     => 'select',
            'class'    => array('my-field-class_ra form-row-wide'),
            'label'    => __('Modelos', $domain),
            'required' => true,
            'options'  => array(
                ''      => __('Sem Modelos', $domain),
                '15.00' => __('Modelo A + 15,00', $domain),
                '25.00' => __('Modelo B + 25,00', $domain),
            ),
        ), '' );
    
        $price = wc_get_price_to_display( $product );
    
        $prices = array(
            ''      => $price,
            '20.00' => 20,
            '25.00' => 25,
            '15.00' => 15,
            '25.00' => 25,
        );
    
        // JS code ?>
        <script>
        jQuery(function($){
            var a  = <?php echo json_encode($prices); ?>,
                b  = 'p.price .numeric-price',
                f1 = 'select[name="amostra"]',
                f2 = 'select[name="amostra_ra"]',
                p  = <?php echo $price; ?>,
                p1 = 0, p2 = 0;
    
            $(f1).on( 'change', function(){
                $.each( a, function( key, value ){
                    if( $(f1).val() == key ){
                        p1 = key == '' ? 0 : value;
                        $(b).html( parseFloat( p + p1 + p2 ).toFixed(2) );
                    }
                });
            });
    
            $(f2).on( 'change', function(){
                $.each( a, function( key, value ){
                    if( $(f2).val() == key ){
                        p2 = key == '' ? 0 : value;
                        $(b).html( parseFloat( p + p1 + p2 ).toFixed(2) );
                    }
                });
            });
        });
        </script>
        <?php
    }
    

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