skip to Main Content

I have adapted the code in the Display selected variation custom fields value in WooCommerce product additional information tab post in order to be able to have custom dimension fields in both the product shipping tab area and the product variations tab area of product info. Here is my adapted code:

// Add custom fields to product shipping tab
add_action( 'woocommerce_product_options_dimensions', 'add_product_options_other_dimensions');
function add_product_options_other_dimensions(){
    global $product_object;

    $product_id = method_exists( $product_object, 'get_id' ) ? $product_object->get_id() : $product_object->id;

    echo '</div><div class="options_group">'; // New option group

    woocommerce_wp_text_input( array(
        'id' => 'real_length',
        'class' => 'short',
        'label'       => __( 'Actual Length', 'woocommerce' ),
        'placeholder' => 'L',
        'desc_tip'    => 'true',
        'description' => __( 'Product actual length (in inches).', 'woocommerce' ),
    ) );

    woocommerce_wp_text_input( array(
        'id' => 'real_width',
        'class' => 'short',
        'label'       => __( 'Actual Width', 'woocommerce' ),
        'placeholder' => 'W',
        'desc_tip'    => 'true',
        'description' => __( 'Product actual width (in inches).', 'woocommerce' ),
    ) );

    woocommerce_wp_text_input( array(
        'id' => 'real_height',
        'class' => 'short',
        'label'       => __( 'Actual Height', 'woocommerce' ),
        'placeholder' => 'H',
        'desc_tip'    => 'true',
        'description' => __( 'Product actual height (in inches).', 'woocommerce' ),
    ) );

}

// Save the custom fields values as meta data
add_action( 'woocommerce_process_product_meta', 'save_product_options_other_dimensions' );
function save_product_options_other_dimensions( $post_id ){

    if( isset( $_POST['real_length'] ) )
        update_post_meta( $post_id, 'real_length', esc_attr( $_POST['real_length'] ) );

    if( isset( $_POST['real_width'] ) )
        update_post_meta( $post_id, 'real_width', esc_attr( $_POST['real_width'] ) );

    if( isset( $_POST['real_height'] ) )
        update_post_meta( $post_id, 'real_height', esc_attr( $_POST['real_height'] ) );

}

// Add custom fields to product variation settings
add_action( 'woocommerce_product_after_variable_attributes','add_variation_options_other_dimensions', 10, 3 );
function add_variation_options_other_dimensions( $loop, $variation_data, $variation ){

    $variation_real_length = get_post_meta($variation->ID,"real_length", true );
    if( ! $variation_real_length ) $variation_real_length = "";

    $variation_real_width = get_post_meta($variation->ID,"real_width", true );
    if( ! $variation_real_width ) $variation_real_width = "";

    $variation_real_height = get_post_meta($variation->ID,"real_height", true );
    if( ! $variation_real_height ) $variation_real_height = "";

    echo '<p class="form-field dimensions_field">';

    woocommerce_wp_text_input( array(
        'id'          => 'real_length' . '_' . $loop,
        'class' => 'short',
        'label'       => __( 'Actual Length', 'woocommerce' ),
        'placeholder' => 'L',
        'desc_tip'    => 'true',
        'description' => __( 'Product actual length (in inches).', 'woocommerce' ),
        'value'       => $variation_real_length
    ) );

    woocommerce_wp_text_input( array(
        'id'          => 'real_width' . '_' . $loop,
        'class' => 'short',
        'label'       => __( 'Actual Width', 'woocommerce' ),
        'placeholder' => 'W',
        'desc_tip'    => 'true',
        'description' => __( 'Product actual width (in inches).', 'woocommerce' ),
        'value'       => $variation_real_width
    ) );

    woocommerce_wp_text_input( array(
        'id'          => '_circuit' . '_' . $loop,
        'class' => 'short',
        'label'       => __( 'Actual Height', 'woocommerce' ),
        'placeholder' => 'H',
        'desc_tip'    => 'true',
        'description' => __( 'Product actual height (in inches).', 'woocommerce' ),
        'value'       => $variation_real_height
    ) );

    echo '</p>';
}


// Save product variation custom fields values
add_action( 'woocommerce_save_product_variation','save_variation_options_other_dimensions', 10 ,2 );
function save_variation_options_other_dimensions( $variation_id, $loop ){

    $the_actual_lenght = $_POST["actual_length_$loop"];
    if( isset($the_actual_lenght) )
        update_post_meta( $variation_id, 'the_actual_lenght', esc_attr($the_actual_lenght) );

    $the_actual_width = $_POST["actual_thickness_$loop"];
    if( isset($the_actual_width) )
        update_post_meta( $variation_id, 'the_actual_width', esc_attr($the_actual_width) );

    $the_actual_height = $_POST["actual_height_$loop"];
    if( isset($the_actual_height) )
        update_post_meta( $variation_id, 'the_actual_height', esc_attr($the_actual_height) );
}

I have two problems though. For one, the code seems to be a little flawed in that it does not seem to save the custom length/width/height fields under the product variation area. I have checked and the flaw is in the original post’s code too.

Secondly, the answer on that post does not detail how to code this so that the inputted information can show on the front end within the Additional Product Information table of Woocommerce product listings.

My question is: how do I alter this code to get it to save the product variation fields and to get the custom field values to display on the Woocommerce Additional Information Tab?

I have been working on this solution for days now and any help would be greatly appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    I ended up paying someone to solve this for me but I figured that I would post the answer here. If anyone out there is looking for a solution to add a second set of dimensions to simple product shipping area and variations area and then have that display in the additional information tab, then here is the code solution:

    /**
     * Plugin Name: Custom Product Fields
     */
    
    defined('ABSPATH') || exit;
    
    /**
     * Add and show simple and variable products.
     * Class NFCPF
     * @package NFCPF
     */
    if (!class_exists('NFCPF')) {
    
        class NFCPF
        {
            /**
             * Hook for call.
             * NFCPF constructor.
             */
            public function __construct()
            {
                // Add simple product fields
                add_action('woocommerce_product_options_shipping', [$this, 'np_show_product_fields'], 101, 3);
                add_action('woocommerce_process_product_meta', [$this, 'np_save_product_fields'], 101, 1);
    
                // Add variable product fields.
                add_action('woocommerce_product_after_variable_attributes', [$this, 'np_show_product_fields'], 101, 3);
                add_action('woocommerce_save_product_variation', [$this, 'np_save_product_fields'], 101, 1);
            }
    
            /**
             * Show product fields in variation and simple product.
             * @param array $loop
             * @param array $variation_data
             * @param array $variation
             */
            public function np_show_product_fields($loop, $variation_data = [], $variation = [])
            {
                $postId = (isset($variation->ID)) ? $variation->ID : get_the_ID();
                $this->np_custom_product_fields($postId);
            }
    
            /**
             * Save the simple product fields.
             * @param int $postId
             */
            public function np_save_product_fields($postId)
            {
                if (isset($postId) && $postId > 0) {
                    $np_product_fields = $this->np_product_fields_arr();
    
                    foreach ($np_product_fields as $key => $custom_field) {
                        $custom_field = (isset($custom_field['id'])) ? $custom_field['id'] : '';
                        $np_updated_product = (isset($_POST[$custom_field][$postId])) ? $_POST[$custom_field][$postId] : '';
                        update_post_meta($postId, $custom_field, $np_updated_product);
                    }
                }
            }
    
            /**
             * Product Fields Array
             * @return array
             */
            public function np_product_fields_arr()
            {
                $np_product_fields = [
                    [
                        'type' => 'input_field',
                        'id' => 'real_length',
                        'class' => 'short',
                        'label' => 'Actual Length',
                        'placeholder' => 'L',
                        'description' => __('Product actual length (in inches).', 'woocommerce')
                    ],
                    [
                        'type' => 'input_field',
                        'id' => 'real_width',
                        'class' => 'short',
                        'label' => 'Actual Width',
                        'placeholder' => 'W',
                        'description' => __('Product actual width (in inches).', 'woocommerce')
                    ],
                    [
                        'type' => 'input_field',
                        'id' => 'real_height',
                        'class' => 'short',
                        'label' => 'Actual Height',
                        'placeholder' => 'H',
                        'description' => __('Product actual height (in inches).', 'woocommerce')
                    ]
                ];
    
                return $np_product_fields;
            }
    
            /**
             * Show Product Fields
             * @param int $postId
             */
            public function np_custom_product_fields($postId)
            {
                $np_product_fields = $this->np_product_fields_arr();
                foreach ($np_product_fields as $key => $custom_field) {
                    $np_field_type = (isset($custom_field['type'])) ? $custom_field['type'] : '';
                    $np_action_function_name = 'np_product_' . $np_field_type;
                    if (method_exists($this, $np_action_function_name)) {
                        $this->$np_action_function_name($custom_field, $postId);
                    }
                }
            }
    
            /**
             * Dynamic input field show on product detail page
             * @param array $custom_field
             * @param int $postId
             */
            public function np_product_input_field($custom_field, $postId)
            {
                $custom_input_field = [
                    'id' => $custom_field['id'] . '[' . $postId . ']',
                    'label' => $custom_field['label'],
                    'class' => $custom_field['class'],
                    'placeholder' => $custom_field['placeholder'],
                    'value' => get_post_meta($postId, $custom_field['id'], true)
                ];
    
                if (isset($custom_field['description'])) {
                    $custom_input_field['desc_tip'] = true;
                    $custom_input_field['description'] = $custom_field['description'];
                }
    
                woocommerce_wp_text_input($custom_input_field);
            }
        }
    
        new NFCPF();
    }
    
    /**
     * Add data to json encoded variation form.
     *
     * @param array $data - this is the variation's json data
     * @param object $product
     * @param object $variation
     * @return array
     */
    function kia_available_variation($data, $product, $variation)
    {
        $kia_data['real_length'] = $variation->get_meta('real_length', true);
        $kia_data['real_width'] = $variation->get_meta('real_width', true);
        $kia_data['real_height'] = $variation->get_meta('real_height', true);
    
        return array_merge($data, $kia_data);
    
    }
    
    add_filter('woocommerce_available_variation', 'kia_available_variation', 10, 3);
    
    /**
     * Add scripts to variable products.
     */
    function kia_on_found_template_for_variable_add_to_cart()
    {
        add_action('wp_print_footer_scripts', 'kia_variable_footer_scripts', 99);
    }
    
    add_action('woocommerce_variable_add_to_cart', 'kia_on_found_template_for_variable_add_to_cart', 30);
    
    function kia_variable_footer_scripts()
    { ?>
        <script type="text/template" id="tmpl-variation-template-extra-data">
            <tr class="woocommerce-product-attributes-item woocommerce-product-attributes-item--attribute_real_length extra-data">
                <th class="woocommerce-product-attributes-item__label"><?php esc_html_e('Length (in)', 'my-text-domain'); ?></th>
                <td class="woocommerce-product-attributes-item__value">{{{ data.variation.real_length }}}</td>
            </tr>
            <tr class="woocommerce-product-attributes-item woocommerce-product-attributes-item--attribute_real_width extra-data">
                <th class="woocommerce-product-attributes-item__label"><?php esc_html_e('Width (in)', 'my-text-domain'); ?></th>
                <td class="woocommerce-product-attributes-item__value">{{{ data.variation.real_width }}}</td>
            </tr>
            <tr class="woocommerce-product-attributes-item woocommerce-product-attributes-item--attribute_real_height extra-data">
                <th class="woocommerce-product-attributes-item__label"><?php esc_html_e('Height (in)', 'my-text-domain'); ?></th>
                <td class="woocommerce-product-attributes-item__value">{{{ data.variation.real_height }}}</td>
            </tr>
        </script>
    
        <script type="text/javascript">
            jQuery(document).ready(function ($) {
                $('form.cart')
                    .on('found_variation', function (event, variation) {
    
                        template = wp.template('variation-template-extra-data');
    
                        $template_html = template({
                            variation: variation
                        });
    
                        // Remove any existing rows.
                        $('#tab-additional_information').find('.woocommerce-product-attributes tr.extra-data').remove();
                        // Add new rows.
                        $('#tab-additional_information').find('.woocommerce-product-attributes tbody').append($template_html);
    
                    })
                    .on('reset_data', function (event, variation) {
                        $('#tab-additional_information').find('.woocommerce-product-attributes tr.extra-data').remove();
                    });
            });
        </script>
        <?php
    }
    
    // Show custom field to simple product
    function np_woocommerce_product_additional_information($product)
    {
        if ($product->is_type('simple')) {
            $product_id = $product->get_id();
            $real_length = get_post_meta($product_id, 'real_length', true);
            $real_width = get_post_meta($product_id, 'real_width', true);
            $real_height = get_post_meta($product_id, 'real_height', true);
            ob_start();
            ?>
            <table class="woocommerce-product-attributes shop_attributes">
                <tbody>
                <tr class="woocommerce-product-attributes-item woocommerce-product-attributes-item--attribute_real_length extra-data">
                    <th class="woocommerce-product-attributes-item__label"><?php esc_html_e('Length (in)', 'np-domain'); ?></th>
                    <td class="woocommerce-product-attributes-item__value"><?php echo $real_length; ?></td>
                </tr>
                <tr class="woocommerce-product-attributes-item woocommerce-product-attributes-item--attribute_real_width extra-data">
                    <th class="woocommerce-product-attributes-item__label"><?php esc_html_e('Width (in)', 'np-domain'); ?></th>
                    <td class="woocommerce-product-attributes-item__value"><?php echo $real_width; ?></td>
                </tr>
                <tr class="woocommerce-product-attributes-item woocommerce-product-attributes-item--attribute_real_height extra-data">
                    <th class="woocommerce-product-attributes-item__label"><?php esc_html_e('Height (in)', 'np-domain'); ?></th>
                    <td class="woocommerce-product-attributes-item__value"><?php echo $real_height; ?></td>
                </tr>
                </tbody>
            </table>
            <?php
            echo ob_get_clean();
        }
    }
    
    add_action('woocommerce_product_additional_information', 'np_woocommerce_product_additional_information', 99, 1);
    

    This solution is particularly useful for anyone looking to have both "shipping dimensions" (which are provided by default by Woocommerce) and "product dimensions" which would be displayed to the customer.


  2. In the meantime you have answered your question yourself (+1) but for the first part of your question:

    "For one, the code seems to be a little flawed in that it does not seem to save the custom length/width/height fields under the product variation area. I have checked and the flaw is in the original post’s code too."

    This may be useful for you or other users


    To add custom fields to the product shipping tab you can use:

    // Add custom fields to product shipping tab
    function action_woocommerce_product_options_dimensions() {
        // New option group
        echo '</div><div class="options_group">';
    
        // Fields
        woocommerce_wp_text_input( array(
            'id'            => 'real_length',
            'class'         => 'short',
            'label'         => __( 'Actual Length', 'woocommerce' ),
            'placeholder'   => 'L',
            'desc_tip'      => 'true',
            'description'   => __( 'Product actual length (in inches).', 'woocommerce' ),
        ) );
    
        woocommerce_wp_text_input( array(
            'id'            => 'real_width',
            'class'         => 'short',
            'label'         => __( 'Actual Width', 'woocommerce' ),
            'placeholder'   => 'W',
            'desc_tip'      => 'true',
            'description'   => __( 'Product actual width (in inches).', 'woocommerce' ),
        ) );
    
        woocommerce_wp_text_input( array(
            'id'            => 'real_height',
            'class'         => 'short',
            'label'         => __( 'Actual Height', 'woocommerce' ),
            'placeholder'   => 'H',
            'desc_tip'      => 'true',
            'description'   => __( 'Product actual height (in inches).', 'woocommerce' ),
        ) );
    }
    add_action( 'woocommerce_product_options_dimensions', 'action_woocommerce_product_options_dimensions' );
    

    However, if you want to display it on 1 line then use this instead of the above code!

    function action_woocommerce_product_options_dimensions() {
        global $product_object;
        
        ?>
        <p class="form-field actual_dimensions_field dimensions_field">
            <?php /* translators: WooCommerce dimension unit*/ ?>
            <label for="product_real_length"><?php printf( __( 'Actual dimensions (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?></label>
            <span class="wrap">
                <input id="product_real_length" placeholder="<?php esc_attr_e( 'Actual length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="product_real_length" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_meta( 'product_real_length' ) ) ); ?>" />
                <input id="product_real_width" placeholder="<?php esc_attr_e( 'Actual width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="product_real_width" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_meta( 'product_real_width' ) ) ); ?>" />
                <input id="product_real_height" placeholder="<?php esc_attr_e( 'Actual height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="product_real_height" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_meta( 'product_real_height' ) ) ); ?>" />
            </span>
            <?php echo wc_help_tip( __( 'Your text', 'woocommerce' ) ); ?>
        </p>
        <?php
    }
    add_action( 'woocommerce_product_options_dimensions', 'action_woocommerce_product_options_dimensions' );
    

    To save fields you can use the woocommerce_admin_process_product_object hook, opposite the outdated woocommerce_process_product_meta hook:

    // Save the custom fields values as meta data
    function action_woocommerce_admin_process_product_object( $product ) {
        // When isset, save
        if ( isset( $_POST['product_real_length'] ) ) {
            $product->update_meta_data( 'product_real_length', esc_attr( $_POST['product_real_length'] ) );
        }
    
        if ( isset( $_POST['product_real_width'] ) ) {
            $product->update_meta_data( 'product_real_width', esc_attr( $_POST['product_real_width'] ) );
        }
    
        if ( isset( $_POST['product_real_height'] ) ) {
            $product->update_meta_data( 'product_real_height', esc_attr( $_POST['product_real_height'] ) );
        }
    }
    add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );
    

    So far adding and saving the fields to the product shipping tab.


    To add and save the fields to the variations tab area, you can use the answer below. But, here are some remarks:

    • The woocommerce_product_after_variable_attributes hook is replaced by woocommerce_variation_options_dimensions as it is better positioned for your question
    • woocommerce_admin_process_variation_object replaces the outdated woocommerce_save_product_variation
    • Optional: to align the fields to the left change form-row-last to form-row-first
    // Add fields
    function action_woocommerce_variation_options_dimensions( $loop, $variation_data, $variation ) {    
        global $post;
    
        // Parent product
        $product_object = wc_get_product( $post->ID );
        
        // Get meta
        $parent_length = wc_format_localized_decimal( $product_object->get_meta( 'product_real_length' ) );
        $parent_width  = wc_format_localized_decimal( $product_object->get_meta( 'product_real_width' ) );
        $parent_height = wc_format_localized_decimal( $product_object->get_meta( 'product_real_height' ) );
        
        $real_length = get_post_meta( $variation->ID, 'variable_real_length', true );
        $real_width = get_post_meta( $variation->ID, 'variable_real_width', true );
        $real_height = get_post_meta( $variation->ID, 'variable_real_height', true );
        
        ?>
        <p class="form-field form-row actual_dimensions_field dimensions_field hide_if_variation_virtual form-row-last">
            <label for="product_real_length">
                <?php
                printf(
                    /* translators: %s: dimension unit */
                    esc_html__( 'Your text (%s)', 'woocommerce' ),
                    esc_html( get_option( 'woocommerce_dimension_unit' ) )
                );
                ?>
            </label>
            <?php echo wc_help_tip( __( 'Your text', 'woocommerce' ) ); ?>
            <span class="wrap">
                <input id="product_real_length" placeholder="<?php echo $parent_length ? esc_attr( $parent_length ) : esc_attr__( 'Actual length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_real_length[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $real_length ) ); ?>" />
                <input id="product_real_width" placeholder="<?php echo $parent_width ? esc_attr( $parent_width ) : esc_attr__( 'Actual width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_real_width[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $real_width ) ); ?>" />
                <input id="product_real_height" placeholder="<?php echo $parent_height ? esc_attr( $parent_height ) : esc_attr__( 'Actual height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="variable_real_height[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $real_height ) ); ?>" />
            </span>
        </p>
        <?php
    }
    add_action( 'woocommerce_variation_options_dimensions', 'action_woocommerce_variation_options_dimensions', 10, 3 );
    
    // Save
    function action_woocommerce_admin_process_variation_object( $variation, $i ) {
        // When isset, save
        if ( isset( $_POST['variable_real_length'][$i] ) ) {
            $variation->update_meta_data( 'variable_real_length', esc_attr( $_POST['variable_real_length'][$i] ) );
        }
        
        if ( isset( $_POST['variable_real_width'][$i] ) ) {
            $variation->update_meta_data( 'variable_real_width', esc_attr( $_POST['variable_real_width'][$i] ) );
        }
        
        if ( isset( $_POST['variable_real_height'][$i] ) ) {
            $variation->update_meta_data( 'variable_real_height', esc_attr( $_POST['variable_real_height'][$i] ) );
        }
    }
    add_action( 'woocommerce_admin_process_variation_object', 'action_woocommerce_admin_process_variation_object', 10, 2 );
    

    Result:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search