phpwordpresswoocommerceproductcustom-fields

Add custom text fields, store their values and display them on Woocommerce product pages


I am trying to do the following: add at least 3 custom text field in a product page in order to show them all together or just one or two when saved. I tried unsuccessfully the following piece of code. Data won't be saved and neither showed, of course. :(

Where am I wrong?

I tried to achieve my goal by mixing a few snippets together:

// Display Fields
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );

// Save Fields
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );

function woo_add_custom_general_fields() {

    global $woocommerce, $post;

    echo '<div class="options_group">';

    // Text Field #1
    woocommerce_wp_text_input( 
        array( 
            'id'          => '_text_field_1', 
            'label'       => __( 'Campo aggiuntivo #1', 'woocommerce' ), 
        )
    );

    // Text Field #2
    woocommerce_wp_text_input( 
        array( 
            'id'          => '_text_field_2', 
            'label'       => __( 'Campo aggiuntivo #2', 'woocommerce' ), 
        )
    );

    // Text Field #3
    woocommerce_wp_text_input( 
        array( 
            'id'          => '_text_field_3', 
            'label'       => __( 'Campo aggiuntivo #3', 'woocommerce' ), 
        )
    );

    echo '</div>';

}

///

function woocommerce_product_custom_fields_save($post_id){

    $woocommerce_custom_product_text_field_1 = $_POST['_text_field_1'];
    if (!empty($woocommerce_custom_product_text_field))
        update_post_meta($post_id, '_custom_product_text_field_1', esc_attr($woocommerce_custom_product_text_field_1));

    $woocommerce_custom_product_text_field_2 = $_POST['_text_field_2'];
    if (!empty($woocommerce_custom_product_number_field))
        update_post_meta($post_id, '_custom_product_text_field_2', esc_attr($woocommerce_custom_product_text_field_2));

    $woocommerce_custom_product_text_field_3 = $_POST['_text_field_3'];
    if (!empty($woocommerce_custom_procut_textarea))
        update_post_meta($post_id, '_custom_product_text_field_3', esc_html($woocommerce_custom_product_text_field_3));
 }

///

add_action( 'woocommerce_before_single_product', 'custom_action', 15 );

function custom_action() {
    // Display Custom Field Value
    echo get_post_meta($post->ID, '_custom_product_text_field_1', true);
    echo get_post_meta($post->ID, '_custom_product_text_field_2', true);
    echo get_post_meta($post->ID, '_custom_product_text_field_3', true);
}

Solution

  • I have revisited a bit your code… Try the following:

    // Admin: Add product custom text fields
    add_action( 'woocommerce_product_options_general_product_data', 'add_custom_general_settings_fields' );
    function add_custom_general_settings_fields() {
    
        echo '<div class="options_group">';
    
        woocommerce_wp_text_input( array(
            'id'          => '_text_field_1',
            'label'       => __( 'Campo aggiuntivo #1', 'woocommerce' ),
        ) );
    
        woocommerce_wp_text_input( array(
            'id'          => '_text_field_2',
            'label'       => __( 'Campo aggiuntivo #2', 'woocommerce' ),
        ) );
    
        woocommerce_wp_text_input( array(
            'id'          => '_text_field_3',
            'label'       => __( 'Campo aggiuntivo #3', 'woocommerce' ),
        ) );
    
        echo '</div>';
    }
    
    // Admin: Save product custom text fields values
    add_action( 'woocommerce_admin_process_product_object', 'save_custom_general_settings_fields_values' );
    function save_custom_general_settings_fields_values( $product ){
        if ( isset($_POST['_text_field_1']) ) {
            $product->update_meta_data( '_text_field_1', sanitize_text_field($_POST['_text_field_1']) );
        }
    
        if ( isset($_POST['_text_field_2']) ) {
            $product->update_meta_data( '_text_field_2', sanitize_text_field($_POST['_text_field_2']) );
        }
    
        if ( isset($_POST['_text_field_3']) ) {
            $product->update_meta_data( '_text_field_3', sanitize_text_field($_POST['_text_field_3']) );
        }
     }
    
    
    // Frontend: Display custom fields values in single product pages
    add_action( 'woocommerce_before_single_product', 'display_custom_fields', 15 );
    function display_custom_fields() {
        global $product;
    
        $values = []; // Initializing
    
        if( $value = $product->get_meta('_text_field_1') ) {
            $values[] = $value; // add the value in the array
        }
    
        if( $value = $product->get_meta('_text_field_2') ) {
            $values[] = $value; // add the value in the array
        }
    
        if( $value = $product->get_meta('_text_field_3') ) {
            $values[] = $value; // add the value in the array
        }
    
        // If the array of values is not empty
        if( count( $values ) > 0 ){
    
            echo '<div>';
    
            // Loop through each existing custom field value
            foreach( $values as $value ) {
                printf('<p>%s</p>', $value);
            }
            echo '</div>';
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.

    But using woocommerce_before_single_product hook doesn't seem to be the best hook as those custom field values are displayed above the product image.