I use a for loop, which takes attendee details for an event. Currently, it generates the statements based on the total number of items in the cart, displaying in checkout some group of fields based on total item quantity.
I'd like to update it to a nested loop: for example, if the customer puts two for event (variable product) for Day 1 (product variation) in their basket, and one ticket for Day 2 (second variation), they would see:
Day 1 Fields for Attendee 1 Fields for Attendee 2
Day 2 Fields for Attendee 1
Here is my code:
//Custom WooCommerce Checkout Fields based on Quantity
add_action( 'woocommerce_before_order_notes', 'person_details' );
function person_details($checkout) {
global $woocommerce;
$count = $woocommerce->cart->cart_contents_count;
for($k=1; $k<= $count; $k++) {
$i++;
print ('<h3>Please enter details of attendee '.$i.'</h3>');
woocommerce_form_field( 'school_year'.$i, array(
'type' => 'radio',
'required' => true,
'class' => array('my-field-class form-row-wide'),
'label' => __('School Year'),
'options' => array(
'Reception' => 'Reception',
'Year 1' => 'Year 1',
'Year 2' => 'Year 2',
'Year 3' => 'Year 3',
'Year 4' => 'Year 4',
'Year 5' => 'Year 5',
'Year 6' => 'Year 6',
'Year 7' => 'Year 7',
),
), $checkout->get_value( 'school_year'.$i ));
woocommerce_form_field( 'cstm_full_name'.$i, array(
'type' => 'text',
'required' => true,
'class' => array('my-field-class form-row-wide'),
'label' => __('Child\s Full name'),
'placeholder' => __('Enter full name'),
), $checkout->get_value( 'cstm_full_name'.$i ));
echo '<div class="clear"></div>';
woocommerce_form_field( 'cstm_phone'.$i, array(
'type' => 'tel',
'required' => true,
'class' => array('my-field-class form-row-first'),
'label' => __('Emergency Contact Number'),
'placeholder' => __('Enter phone number'),
), $checkout->get_value( 'cstm_phone'.$i ));
echo '<div class="clear"></div>';
woocommerce_form_field( 'photo_consent'.$i, array(
'type' => 'radio',
'required' => true,
'class' => array('my-field-class form-row-wide'),
'label' => __('Photograph Consent?'),
'options' => array(
'Yes' => 'Yes',
'No' => 'No',
),
), $checkout->get_value( 'photo_consent'.$i ));
}
}
/**
* Save value of fields
*/
add_action('woocommerce_checkout_update_order_meta', 'customise_checkout_field_update_order_meta');
function customise_checkout_field_update_order_meta($order_id) {
global $woocommerce;
$count = $woocommerce->cart->cart_contents_count;
for($k=1; $k<= $count; $k++) {
$i++;
if (!empty($_POST['school_year'.$i])) {
update_post_meta($order_id, 'School Year of Attendee'.$i, sanitize_text_field($_POST['school_year'.$i]));
}
if (!empty($_POST['cstm_full_name'.$i])) {
update_post_meta($order_id, 'Name of Attendee' .$i, sanitize_text_field($_POST['cstm_full_name'.$i]));
}
if (!empty($_POST['cstm_phone'.$i])) {
update_post_meta($order_id, 'Emergency Contact' .$i, sanitize_text_field($_POST['cstm_phone'.$i]));
}
if (!empty($_POST['photo_consent'.$i])) {
update_post_meta($order_id, 'Attendee Photo Consent' .$i, sanitize_text_field($_POST['photo_consent'.$i]));
}
}
}
/**
* Add fields to order emails
**/
add_filter('woocommerce_email_order_meta_keys', 'my_custom_checkout_field_order_meta_keys');
function my_custom_checkout_field_order_meta_keys( $keys ) {
for($k=1; $k<= 50; $k++) {
$i++;
$keys[] = 'School Year of Attendee'.$i;
$keys[] = 'Name of Attendee'.$i;
$keys[] = 'Emergency Contact'.$i;
$keys[] = 'Attendee Photo Consent'.$i;
}
return $keys;
}
I have tried nesting another for each loop, using $woocommerce->cart->get_cart(); but I'm a bit out of my depth…
I have enabled nested loops, revisiting your code, to get what you are expecting in your question. Here is my code:
Code goes in functions.php file of the active child theme (or active theme). Tested and works.