phpwordpresswoocommercecheckoutcustom-fields

Additional fields based on the quantity of products selected


I have to make a site to sell course enrollments, and to do, so I'm using WooCommerce. Both single people and companies who will make multiple registrations for their employees will enroll in the courses, I would like to be able to have fields like the standard WooCommerce checkout filled in if it is a single person. Otherwise, if it is a company (which I have to register more depends for the same course) standard fields for company data and fields for employee data that are repeated based on the quantity selected in the product. Once the order is completed, I need to see all the data on the order page and in the emails. I tried this plug-in, it works, but I can't show a group of fields based on quantity, do you think this feature can be added somehow? Otherwise, I found this code

function person_details( $checkout ) {

    global $woocommerce;
    $count = $woocommerce->cart->cart_contents_count;
    $i = 0;

    for( $k=1; $k<= $count; $k++ ) {
        $i++;
        print ('Dati iscritto n. '.$i.'');
        
        woocommerce_form_field( 'cstm_full_name'.$i, array(
            'type'          => 'text',
            'class'         => array('my-field-class form-row-first'),
            'label'         => __('Nome e cognome'),
            'placeholder'   => __(''),
            'required' => true,
        ), $checkout->get_value( 'cstm_full_name'.$i ));
        
        
        
            woocommerce_form_field( 'cstm_email'.$i, array(
                'type'          => 'email',
                'required' => true,
                'class'         => array( 'my-field-class form-row-last' ),
                'label'         => __( 'Email' ),
                
            ), $checkout->get_value( 'cstm_email'.$i ));
            
            woocommerce_form_field( 'cstm_phone'.$i, array(
                'type'          => 'text',
                'class'         => array('my-field-class form-row-first'),
                'label'         => __('Numero di telefono'),
                'placeholder'   => __(''),
                'required' => true,
            ), $checkout->get_value( 'cstm_phone'.$i ));
            
            woocommerce_form_field( 'cstm_address'.$i, array(
                'type'          => 'textarea',
                'class'         => array('my-field-class form-row-last'),
                'label'         => __('Indirizzo di residenza'),
                'placeholder'   => __(''),
                'required' => true,
            ), $checkout->get_value( 'cstm_address'.$i ));
        echo '<div class="clear"></div>';
            
        echo '<div class="clearbox"></div>';
    }
}
add_action( 'woocommerce_before_order_notes', 'person_details' );

function customise_checkout_field_update_order_meta($order_id)
{
    global $woocommerce;
    $count = $woocommerce->cart->cart_contents_count;
    $i = 0;
    for($k=1; $k<= $count; $k++) {
        $i++;
        if (!empty($_POST['cstm_full_name'.$i])) {
            update_post_meta($order_id, 'Nome e cognome'.$i, sanitize_text_field($_POST['cstm_full_name'.$i]));
        }
        if (!empty($_POST['cstm_email'.$i])) {
            update_post_meta($order_id, 'email'.$i, sanitize_text_field($_POST['cstm_email'.$i]));
        }
        if (!empty($_POST['cstm_phone'.$i])) {
            update_post_meta($order_id, 'Numero di telefono'.$i, sanitize_text_field($_POST['cstm_phone'.$i]));
        }
        if (!empty($_POST['cstm_address'.$i])) {
            update_post_meta($order_id, 'Indirizzo di residenza'.$i, sanitize_text_field($_POST['cstm_address'.$i]));
        }
        /*if ( isset( $_POST['cstm_groep'.$i] )){
            $value = sanitize_text_field( $_POST['cstm_groep'.$i] );
            update_post_meta( $post->ID, 'cstm_groep'.$i, $value );  
        }*/
    }
}
add_action('woocommerce_checkout_update_order_meta', 'customise_checkout_field_update_order_meta');

function add_email_custom_order_meta( $order, $sent_to_admin, $plain_text ){

    $quantity = 0;      
    foreach ( $order->get_items() as $item_id => $item ) {
        $quantity = $quantity + $item->get_quantity();
    }
    
    $order_id = $order->get_order_number();
    echo "<ul>";
        $i = 0;
        for( $k=1; $k <= $quantity; $k++ ) {
            $i++;
            echo "<li>Nome e cognome: ".get_post_meta($order_id, 'Nome e cognome'.$i, true )."</li>";
            echo "<li>Email: ".get_post_meta($order_id, 'Email'.$i, true )."</li>";
            echo "<li>Numero di telefono: ".get_post_meta($order_id, 'Numero di telefono'.$i, true )."</li>";
            echo "<li>Indirizzo di residenza: ".get_post_meta($order_id, 'Indirizzo di residenza'.$i, true )."</li>";
            
            
        }
    echo "</ul>";

}
add_action( 'woocommerce_email_order_meta', 'add_email_custom_order_meta', 10, 3 );
// display the extra data in the order admin panel
function display_order_custom_data_in_admin_order_overview_page( $order ){  ?>
    <div class="order_data_column" style="width: 100% !important;">
        <h4><?php _e( 'Your label' ); ?></h4>
        <?php 
            $quantity = 0;      
            foreach ( $order->get_items() as $item_id => $item ) {
                $quantity = $quantity + $item->get_quantity();
            }
            
            $order_id = $order->get_order_number();
            echo "<ul>";
                $i = 0;
                for( $k=1; $k <= $quantity; $k++ ) {
                    $i++;
                    echo "<li>Nome e cognome: ".get_post_meta($order_id, 'Nome e cognome'.$i, true )."</li>";
                    echo "<li>Email: ".get_post_meta($order_id, 'Email'.$i, true )."</li>";
                    echo "<li>Numero di telefono: ".get_post_meta($order_id, 'Numero di telefono'.$i, true )."</li>";
                    echo "<li>Indirizzo di residenza: ".get_post_meta($order_id, 'Indirizzo di residenza'.$i, true )."</li>";
                    
                }
            echo "</ul>";    
        ?>
    </div>
<?php }
add_action( 'woocommerce_admin_order_data_after_order_details', 'display_order_custom_data_in_admin_order_overview_page' );

This works, it adds the fields based on the quantity, but I can't see the data in the email and in the order page, and also I would like to put some conditions like if you select I'm a private person show i standard fields otherwise if you select I am a company it will show a group of fields to be filled in only once and more other groups of equal fields to be filled in, as many as the selected quantity.

The code is old maybe the hooks of WooCommerce have changed over time, I tried to look, but I could not make it work. do you know if there is an easier way to do it like with some plugin or if you can mix some of the plugin mentioned above and the code?

For example, using the fields and conditions of the plugin but choosing with the code which group of fields to show based on the quantity?

update this is the complete code present in the function.php file

<?php
function my_theme_enqueue_styles() { 
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );


/**
 * Add the product's short description (excerpt) to the WooCommerce shop/category pages.
 */

function woocommerce_after_shop_loop_item_title_short_description() {
    global $product;
    if ( ! $product->get_short_description() ) return; ?>
    <div itemprop="description">
       <?php echo apply_filters( 'woocommerce_short_description', $product->get_short_description() ) ?>
    </div>
    <?php
}

add_action('woocommerce_after_shop_loop_item_title', 'woocommerce_after_shop_loop_item_title_short_description', 5);



// Add "Add to Cart" buttons in Divi shop pages
add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 20 );
// To change add to cart text on single product page
add_filter( 'woocommerce_product_single_add_to_cart_text', 'woocommerce_custom_single_add_to_cart_text' );
function woocommerce_custom_single_add_to_cart_text() {
return __( 'Iscriviti', 'woocommerce' );
}
// To change add to cart text on product archives(Collection) page
add_filter( 'woocommerce_product_add_to_cart_text', 'woocommerce_custom_product_add_to_cart_text' );
function woocommerce_custom_product_add_to_cart_text() {
return __( 'Vedi', 'woocommerce' );
}



function category_single_product(){

    $product_cats = wp_get_post_terms( get_the_ID(), 'product_cat' );

    if ( $product_cats && ! is_wp_error ( $product_cats ) ){

        $single_cat = array_shift( $product_cats ); ?>

        <p itemprop="name" class="card product_category_title"><span><?php echo $single_cat->name; ?></span></p>

<?php }
}
add_action( 'woocommerce_before_shop_loop_item_title', 'category_single_product', 25 );

// campi checkout ordine in base alla quantità


/**
 * Display field value on the order edit page   DA TOGLIERE
 */
/*add_action( 'woocommerce_admin_order_data_after_billing_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );

function my_custom_checkout_field_display_admin_order_meta($order){
    echo '<p><strong>'.__('My Field').':</strong> ' . get_post_meta( $order->id, 'Full name', true ) . '</p>';
}*/










/* nuovo test custom field*/
add_action( 'woocommerce_before_order_notes', 'persons_details' );
function persons_details( $checkout ) {
    $count = WC()->cart->get_cart_contents_count();
    $i = 0;

    for( $k=1; $k<= $count; $k++ ) {
        $i++;
        echo '<div><strong>'. __('Dati iscritto n. ') . $i . '</strong></div>';
        
        woocommerce_form_field( 'cstm_full_name' . $i, array(
            'type'          => 'text',
            'class'         => array('my-field-class form-row-first'),
            'label'         => __("Nome e cognome"),
            'placeholder'   => __(""),
            'required'      => true,
        ), $checkout->get_value( 'cstm_full_name' . $i ));
        
        woocommerce_form_field( 'cstm_email' . $i, array(
            'type'          => 'email',
            'class'         => array( 'my-field-class form-row-last' ),
            'label'         => __( "Email" ),
            'placeholder'   => __(""),
            'required'      => true,
        ), $checkout->get_value( 'cstm_email' . $i ));
        
        woocommerce_form_field( 'cstm_phone' . $i, array(
            'type'          => 'text',
            'class'         => array('my-field-class form-row-first'),
            'label'         => __("Numero di telefono"),
            'placeholder'   => __(""),
            'required'      => true,
        ), $checkout->get_value( 'cstm_phone' . $i ));
        
        woocommerce_form_field( 'cstm_address' . $i, array(
            'type'          => 'textarea',
            'class'         => array('my-field-class form-row-last'),
            'label'         => __("Indirizzo di residenza"),
            'placeholder'   => __(""),
            'required'      => true,
        ), $checkout->get_value( 'cstm_address' . $i ));
        
        echo '<div class="clear"></div>
        <div class="clearbox"></div>';
    }
}


add_action( 'woocommerce_checkout_create_order', 'save_custom_checkout_field_order_meta' );
function save_custom_checkout_field_order_meta( $order )
{
    $count = WC()->cart->get_cart_contents_count();
    $order->update_meta_data( 'cstm_items_count', intval($count) ); // Save the cart contents count as meta data
    
    $i = 0;
    for($k=1; $k<= $count; $k++) {
        $i++;
        if ( isset($_POST['cstm_full_name'.$i]) && ! empty($_POST['cstm_full_name'.$i]) ) {
            $order->update_meta_data( 'cstm_full_name'.$i, sanitize_text_field($_POST['cstm_full_name'.$i]) );
        }
        if ( isset($_POST['cstm_email'.$i]) && ! empty($_POST['cstm_email'.$i]) ) {
            $order->update_meta_data( 'cstm_email'.$i, sanitize_text_field($_POST['cstm_email'.$i]) );
        }
        if ( isset($_POST['cstm_phone'.$i]) && ! empty($_POST['cstm_phone'.$i])) {
            $order->update_meta_data( 'cstm_phone'.$i, sanitize_text_field($_POST['cstm_phone'.$i]) );
        }
        if ( isset($_POST['cstm_address'.$i]) && ! empty($_POST['cstm_address'.$i])) {
            $order->update_meta_data( 'cstm_address'.$i, sanitize_text_field($_POST['cstm_address'.$i]) );
        }
    }
}

add_action( 'woocommerce_email_order_meta', 'add_email_custom_order_meta', 10, 3 );
function add_email_custom_order_meta( $order, $sent_to_admin, $plain_text ){
    $quantity = $order->get_meta('cstm_items_count'); // Get items quantity count from meta data
    
    echo '<ul>';
    $i = 0;
    for( $k=1; $k <= $quantity; $k++ ) {
        $i++;
        echo '<li><strong>'. __("Dati iscritto n. ") . $i . '<strong></li>
        <li>' . __("Nome e cognome: ") . $order->get_meta('cstm_full_name'.$i) . '</li>
        <li>' . __("Email: ") . $order->get_meta('cstm_email'.$i) . '</li>
        <li>' . __("Numero di telefono: ") . $order->get_meta('cstm_phone'.$i) . '</li>
        <li>' . __("Indirizzo di residenza: ") . $order->get_meta('cstm_address'.$i) . '</li>';
    }
    echo '</ul>';
}

add_action( 'woocommerce_admin_order_data_after_order_details', 'display_custom_fields_in_admin_order_pages' );
function display_custom_fields_in_admin_order_pages( $order ){ 
    $quantity = $order->get_meta('cstm_items_count'); // Get items quantity count from meta data  
    
    echo '<div class="order_data_column" style="width: 100% !important;">
        <h4>' . __( 'Your label' ) . '</h4>
        <ul>';
        $i = 0;
        for( $k=1; $k <= $quantity; $k++ ) {
            $i++;
            echo '<li><strong>'. __("Dati iscritto n. ") . $i . '<strong></li>
            <li>' . __("Nome e cognome: ") . $order->get_meta('cstm_full_name'.$i) . '</li>
            <li>' . __("Email: ") . $order->get_meta('cstm_email'.$i) . '</li>
            <li>' . __("Numero di telefono: ") . $order->get_meta('cstm_phone'.$i) . '</li>
            <li>' . __("Indirizzo di residenza: ") .$order->get_meta('cstm_address'.$i) . '</li>';
        }
        echo '</ul>
    </div>';
}

Solution

  • Here is your revisited working code, using the correct syntax and last WooCommerce Hooks:

    add_action( 'woocommerce_before_order_notes', 'persons_details' );
    function persons_details( $checkout ) {
        $count = WC()->cart->get_cart_contents_count();
        $i = 0;
    
        for( $k=1; $k<= $count; $k++ ) {
            $i++;
            echo '<div><strong>'. __('Dati iscritto n. ') . $i . '</strong></div>';
            
            woocommerce_form_field( 'cstm_full_name' . $i, array(
                'type'          => 'text',
                'class'         => array('my-field-class form-row-first'),
                'label'         => __("Nome e cognome"),
                'placeholder'   => __(""),
                'required'      => true,
            ), $checkout->get_value( 'cstm_full_name' . $i ));
            
            woocommerce_form_field( 'cstm_email' . $i, array(
                'type'          => 'email',
                'class'         => array( 'my-field-class form-row-last' ),
                'label'         => __( "Email" ),
                'placeholder'   => __(""),
                'required'      => true,
            ), $checkout->get_value( 'cstm_email' . $i ));
            
            woocommerce_form_field( 'cstm_phone' . $i, array(
                'type'          => 'text',
                'class'         => array('my-field-class form-row-first'),
                'label'         => __("Numero di telefono"),
                'placeholder'   => __(""),
                'required'      => true,
            ), $checkout->get_value( 'cstm_phone' . $i ));
            
            woocommerce_form_field( 'cstm_address' . $i, array(
                'type'          => 'textarea',
                'class'         => array('my-field-class form-row-last'),
                'label'         => __("Indirizzo di residenza"),
                'placeholder'   => __(""),
                'required'      => true,
            ), $checkout->get_value( 'cstm_address' . $i ));
            
            echo '<div class="clear"></div>
            <div class="clearbox"></div>';
        }
    }
    
    
    add_action( 'woocommerce_checkout_create_order', 'save_custom_checkout_field_order_meta' );
    function save_custom_checkout_field_order_meta( $order )
    {
        $count = WC()->cart->get_cart_contents_count();
        $order->update_meta_data( 'cstm_items_count', intval($count) ); // Save the cart contents count as meta data
        
        $i = 0;
        for($k=1; $k<= $count; $k++) {
            $i++;
            if ( isset($_POST['cstm_full_name'.$i]) && ! empty($_POST['cstm_full_name'.$i]) ) {
                $order->update_meta_data( 'cstm_full_name'.$i, sanitize_text_field($_POST['cstm_full_name'.$i]) );
            }
            if ( isset($_POST['cstm_email'.$i]) && ! empty($_POST['cstm_email'.$i]) ) {
                $order->update_meta_data( 'cstm_email'.$i, sanitize_text_field($_POST['cstm_email'.$i]) );
            }
            if ( isset($_POST['cstm_phone'.$i]) && ! empty($_POST['cstm_phone'.$i])) {
                $order->update_meta_data( 'cstm_phone'.$i, sanitize_text_field($_POST['cstm_phone'.$i]) );
            }
            if ( isset($_POST['cstm_address'.$i]) && ! empty($_POST['cstm_address'.$i])) {
                $order->update_meta_data( 'cstm_address'.$i, sanitize_text_field($_POST['cstm_address'.$i]) );
            }
        }
    }
    
    add_action( 'woocommerce_email_order_meta', 'add_email_custom_order_meta', 10, 3 );
    function add_email_custom_order_meta( $order, $sent_to_admin, $plain_text ){
        $quantity = $order->get_meta('cstm_items_count'); // Get items quantity count from meta data
        
        echo '<ul>';
        $i = 0;
        for( $k=1; $k <= $quantity; $k++ ) {
            $i++;
            echo '<li><strong>'. __("Dati iscritto n. ") . $i . '<strong></li>
            <li>' . __("Nome e cognome: ") . $order->get_meta('cstm_full_name'.$i) . '</li>
            <li>' . __("Email: ") . $order->get_meta('cstm_email'.$i) . '</li>
            <li>' . __("Numero di telefono: ") . $order->get_meta('cstm_phone'.$i) . '</li>
            <li>' . __("Indirizzo di residenza: ") . $order->get_meta('cstm_address'.$i) . '</li>';
        }
        echo '</ul>';
    }
    
    add_action( 'woocommerce_admin_order_data_after_order_details', 'display_custom_fields_in_admin_order_pages' );
    function display_custom_fields_in_admin_order_pages( $order ){ 
        $quantity = $order->get_meta('cstm_items_count'); // Get items quantity count from meta data  
        
        echo '<div class="order_data_column" style="width: 100% !important;">
            <h4>' . __( 'Your label' ) . '</h4>
            <ul>';
            $i = 0;
            for( $k=1; $k <= $quantity; $k++ ) {
                $i++;
                echo '<li><strong>'. __("Dati iscritto n. ") . $i . '<strong></li>
                <li>' . __("Nome e cognome: ") . $order->get_meta('cstm_full_name'.$i) . '</li>
                <li>' . __("Email: ") . $order->get_meta('cstm_email'.$i) . '</li>
                <li>' . __("Numero di telefono: ") . $order->get_meta('cstm_phone'.$i) . '</li>
                <li>' . __("Indirizzo di residenza: ") .$order->get_meta('cstm_address'.$i) . '</li>';
            }
            echo '</ul>
        </div>';
    }
    
    

    Addition

    Mandatory (required) custom checkout fields validation:

    add_action( 'woocommerce_after_checkout_validation', 'custom_checkout_fields_validation', 20, 2 );
    function custom_checkout_fields_validation( $data, $errors ){
        $count = WC()->cart->get_cart_contents_count();
        
        $i = 0;
        for($k=1; $k<= $count; $k++) {
            $i++;
            if ( isset($_POST['cstm_full_name'.$i]) && empty($_POST['cstm_full_name'.$i]) ) {
                $errors->add( 'cstm_full_name'.$i,  __( "Si prega di compilare iscritto n. $i \"Nome e cognome\"" ), 'error' );
            }
            if ( isset($_POST['cstm_email'.$i]) && empty($_POST['cstm_email'.$i]) ) {
                $errors->add( 'cstm_email'.$i,  __( "Si prega di compilare iscritto n. $i \"Email\"" ), 'error' );
            }
            if ( isset($_POST['cstm_phone'.$i]) && empty($_POST['cstm_phone'.$i])) {
                $errors->add( 'cstm_phone'.$i,  __( "Si prega di compilare iscritto n. $i \"Numero di telefono\"" ), 'error' );
            }
            if ( isset($_POST['cstm_address'.$i]) && empty($_POST['cstm_address'.$i])) {
                $errors->add( 'cstm_address'.$i,  __( "Si prega di compilare iscritto n. $i \"Indirizzo di residenza\"" ), 'error' );
            }
        }
    }
    

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

    On Admin single Order Pages:

    enter image description here

    On email notifications:

    enter image description here

    In the database, under wp_postmeta table for the order ID (post ID):

    enter image description here