Search code examples
wordpresswoocommercebackendproduct

Add custom fields to WooComerce product setting pages in the shipping tab and apply automatic calculations based on the values


Based on the answers to the following questions:

I managed to create two extra fields in the WooCommerce Shipping Options:

  • Field to add loading meters
  • Field to add shipping weight

These fields will get a value either by an admin user editing the field, either by a calculation that helps us to prefill the field with a value.

Underneath snippet shows the creation of the field by adding the snippets to the functions.php file.

add_action('woocommerce_product_options_shipping', function() {
  
    woocommerce_wp_text_input( 
        array( 
            'id'            => '_loading_meters', 
            'label'         => __('Loading meters', 'woocommerce'), 
            'desc_tip'      => 'true',
            'description'   => __( 'Vul hier de laadmeters in', 'woocommerce' ),
            'type'          => 'number',
            'custom_attributes' => array(
                            'step'  => 'any',
                            'min'   => '0'
                        ) 
        )
    );      

    woocommerce_wp_text_input( 
        array( 
            'id'            => '_loading_weight', 
            'label'         => __('Loading weight', 'woocommerce'), 
            'desc_tip'      => 'true',
            'description'   => __( 'Vul hier het laadgewicht in', 'woocommerce' ),
            'type'          => 'number',
            'custom_attributes' => array(
                            'step'  => 'any',
                            'min'   => '0'
                        ) 
        )
    );
    
});

The second snippet is saving the values that were manually added by the admin user. This snippet is also added to the functions.php file.

add_action('woocommerce_process_product_meta', function($post_id) {
    $product = wc_get_product($post_id);
    $num_loading_meters = isset($_POST['_loading_meters']) ? $_POST['_loading_meters'] : '';
    $num_loading_weight = isset($_POST['_loading_weight']) ? $_POST['_loading_weight'] : '';
    $product->update_meta_data('_loading_meters', sanitize_text_field($num_loading_meters));
    $product->update_meta_data('_loading_weight', sanitize_text_field($num_loading_weight)); $product->save();
});

As an end result, I would like to achieve both field filled in automatically using a calcuation, but still being editable by an admin user.

The calculation for the loading meters:

  • (lenght (m)) x (height (m)) / 2.4

The calculation for the loading weight:

  • Loading meters * 1750

Is there anyone who can point me in the right direction?


Solution

  • For the calculation you can use $product->get_length() and $product->get_height()

    The calculation can be saved automatically, but be aware that if you are going to adjust the values ​​manually you have to indicate this somewhere. Otherwise the automatic calculation will be overwritten by the manually entered values ​​or vice versa when saving.

    To prevent this, I have added an extra field, namely a checkbox. When checked, the manually entered values ​​will be saved, if not, the calculation will be performed automatically and these values ​​will be saved

    So you get:

    // Add custom fields to product shipping tab
    function action_woocommerce_product_options_shipping() {
        // Checkbox
        woocommerce_wp_checkbox( 
            array( 
            'id'             => '_loading_checkbox',
            'label'          => __( 'My checkbox', 'woocommerce' ),
            'desc_tip'       => false,
            'description'    => __( 'If this is checked, the values ​​entered manually will be saved against the values ​​of the automatic calculation', 'woocommerce' )
            )
        );
        
        // Field loading meters
        woocommerce_wp_text_input(
            array( 
                'id'                => '_loading_meters', 
                'label'             => __( 'Loading meters', 'woocommerce' ), 
                'desc_tip'          => true,
                'description'       => __( 'Vul hier de laadmeters in', 'woocommerce' ),
                'type'              => 'number',
                'custom_attributes' => array(
                    'step'  => 'any',
                    'min'   => '0'
                )
            )
        );
        
        // Field loading weight
        woocommerce_wp_text_input( 
            array( 
                'id'                => '_loading_weight', 
                'label'             => __('Loading weight', 'woocommerce'), 
                'desc_tip'          => true,
                'description'       => __( 'Vul hier het laadgewicht in', 'woocommerce' ),
                'type'              => 'number',
                'custom_attributes' => array(
                    'step'  => 'any',
                    'min'   => '0'
                )
            )
        );
    }
    add_action( 'woocommerce_product_options_shipping', 'action_woocommerce_product_options_shipping', 10, 0 );
    
    // Save
    function action_woocommerce_admin_process_product_object( $product ) {
        // Checkbox has been checked
        if ( isset( $_POST['_loading_checkbox'] ) ) {
            // Isset
            if ( isset( $_POST['_loading_meters'] ) ) {
                $product->update_meta_data( '_loading_meters', sanitize_text_field( $_POST['_loading_meters'] ) );
            }
            
            // Isset
            if ( isset( $_POST['_loading_weight'] ) ) {
                $product->update_meta_data( '_loading_weight', sanitize_text_field( $_POST['_loading_weight'] ) );
            }
        } else {
            // Initialize
            $loading_meters = '';
            
            // Isset
            if ( isset( $_POST['_loading_meters'] ) ) {
                // Get values
                $height = $product->get_length();
                $length = $product->get_height();
    
                // NOT empty
                if ( ! empty( $height ) && ! empty( $length ) ) {
                    // Calculation
                    $loading_meters = ( $length * $height ) / 2.4;
                    
                    // Update meta
                    $product->update_meta_data( '_loading_meters', $loading_meters );
                }
            }
    
            // Isset and NOT empty
            if ( isset( $_POST['_loading_weight'] ) && ! empty( $loading_meters ) ) {
                // Calculation
                $loading_weight = $loading_meters * 1750;
                
                // Update meta
                $product->update_meta_data( '_loading_weight', $loading_weight );
            }
        }
    }
    add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );
    

    Result:

    enter image description here