I have created some custom checkout fields based on whether a customer buys 1 or 2 items. The fields are called: 'Voorletters', 'Roepnaam', 'Achternaam' and 'Geboortedatum'. The code works since the data shows up in our Wordpress backend below the respective orders, but we want to include it in our e-mails as well. Ideally we would want to include this in the order completed mail that the customer receives after a successful payment, but also to the confirmation mail that the admin receives upon a new order.
Based on Add multiple custom checkout fields grouped in two columns on WooCommerce answer code, here it's what I have:
// Utility function: Get specific product total cart item quantity
function get_specific_cart_item_quantity() {
$targeted_id = 5027; // <== Product ID to check for.
$item_qty = 0; // Initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $item ) {
if ( $item['product_id'] == $targeted_id ) {
$item_qty += $item['quantity'];
}
}
return $item_qty;
}
// Add custom checkout fields
add_action('woocommerce_checkout_before_customer_details', 'add_custom_checkout_fields');
function add_custom_checkout_fields() {
$item_qty = get_specific_cart_item_quantity();
if ( $item_qty ) {
$domain = 'woocommerce';
echo '<div id="custom_checkout_fields">
<h3>' . __('<b>Persoonsgegevens BHV</b>', $domain) . '</h3>
<p>' . __('Vul a.u.b. de persoonsgegevens van de BHV kandidaten in hieronder.', $domain) . '</p>
<div class="custom-fields-container">';
$qty1 = $item_qty % 2 == 0 ? $item_qty / 2 : ( $item_qty == 1 ? 1 : ($item_qty + 1) / 2 );
$qty2 = $item_qty == 1 ? 1 : 2;
// Multi-loop to display custom fields based on quantity in 2 columns
for ( $k = 1; $k <= $qty1; $k++ ) {
$qty2 = $item_qty % 2 != 0 && $k == $qty1 ? 1 : 2;
// 2nd Loop (letters)
foreach ( array('Voorletters', 'Roepnaam', 'Achternaam', 'Geboortedatum') as $letter ) {
$key = strtolower($letter);
// 3rd Loop (Columns)
for ( $h = 1; $h <= $qty2; $h++ ) {
$class = $item_qty > 1 ? (($h % 2 == 0) ? 'last' : 'first' ) : 'wide';
$class = $item_qty % 2 != 0 && $k == $qty1 ? 'wide' : $class;
$index = $item_qty == 1 ? 1 : 2;
$index = in_array($class, ['first', 'wide']) ? ($k*2)-1 : $k*2;
$field = "custom_field_{$key}{$index}";
$label = sprintf('%s %d %s', __('Kandidaat', $domain), $index, $letter);
woocommerce_form_field( $field, array(
'type' => 'text',
'label' => $label,
'placeholder' => '',
'class' => array('custom-field form-row-'.$class),
'required' => true, // or false
), WC()->checkout->get_value( $field ) );
}
}
}
echo '</div></div>';
}
}
// Validate custom fields
add_action( 'woocommerce_after_checkout_validation', 'validate_custom_checkout_fields', 10, 2 );
function validate_custom_checkout_fields( $data, $errors ) {
if ( did_action('woocommerce_checkout_process') >= 2 ) return;
$item_qty = get_specific_cart_item_quantity();
if ( $item_qty ) {
$domain = 'woocommerce';
$break = false;
// 1st Loop (Letters)
foreach ( array('Voorletters', 'Roepnaam', 'Achternaam', 'Geboortedatum') as $letter ) {
$key = strtolower($letter);
// 2nd Loop (Numbers)
for ( $i = 1; $i <= $item_qty; $i++ ) {
$field = "custom_field_{$key}{$i}";
if ( isset($_POST[$field]) && empty($_POST[$field]) ) {
$errors->add( 'validation', __('Vul a.u.b. de verplichte velden in.', $domain), 'error' );
$break = true;
break;
}
}
if ( $break ) break;
}
}
}
// Save custom field data as custom order meta data
add_action( 'woocommerce_checkout_create_order', 'save_custom_checkout_fields', 10, 2 );
function save_custom_checkout_fields( $order, $data ) {
$item_qty = get_specific_cart_item_quantity();
if ( $item_qty ) {
// 1st Loop (Letters)
foreach ( array('Voorletters', 'Roepnaam', 'Achternaam', 'Geboortedatum') as $letter ) {
$key = strtolower($letter);
// 2nd Loop (Numbers)
for ( $i = 1; $i <= $item_qty; $i++ ) {
$field = "custom_field_{$key}{$i}";
if ( isset($_POST[$field]) && ! empty($_POST[$field]) ) {
$order->update_meta_data( $field, sanitize_text_field($_POST[$field]) );
}
}
}
}
}
I have revisited lightly all your code. The following will display your custom fields data in Admin "New order" and "Customer completed order" email notifications:
// Utility function: Get specific product total cart item quantity
function get_specific_cart_item_quantity() {
$targeted_id = 5027; // <== Product ID to check for.
$item_qty = 0; // Initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $item ) {
if ( $item['product_id'] == $targeted_id ) {
$item_qty += $item['quantity'];
}
}
return $item_qty;
}
// Utility function: Get participant fields labels
function get_candidate_fields_labels() {
return array('Voorletters', 'Roepnaam', 'Achternaam', 'Geboortedatum');
}
// Add custom checkout fields
add_action('woocommerce_checkout_before_customer_details', 'add_custom_checkout_fields');
function add_custom_checkout_fields() {
$item_qty = get_specific_cart_item_quantity();
if ( $item_qty ) {
$domain = 'woocommerce';
echo '<div id="custom_checkout_fields">
<h3>' . __('<b>Persoonsgegevens BHV</b>', $domain) . '</h3>
<p>' . __('Vul a.u.b. de persoonsgegevens van de BHV kandidaten in hieronder.', $domain) . '</p>
<div class="custom-fields-container">';
$qty1 = $item_qty % 2 == 0 ? $item_qty / 2 : ( $item_qty == 1 ? 1 : ($item_qty + 1) / 2 );
$qty2 = $item_qty == 1 ? 1 : 2;
// Multi-loop to display custom fields based on quantity in 2 columns
for ( $k = 1; $k <= $qty1; $k++ ) {
$qty2 = $item_qty % 2 != 0 && $k == $qty1 ? 1 : 2;
// 2nd Loop (letters)
foreach ( get_candidate_fields_labels() as $letter ) {
$key = strtolower($letter);
// 3rd Loop (Columns)
for ( $h = 1; $h <= $qty2; $h++ ) {
$class = $item_qty > 1 ? (($h % 2 == 0) ? 'last' : 'first' ) : 'wide';
$class = $item_qty % 2 != 0 && $k == $qty1 ? 'wide' : $class;
$index = $item_qty == 1 ? 1 : 2;
$index = in_array($class, ['first', 'wide']) ? ($k*2)-1 : $k*2;
$field = "custom_field_{$key}{$index}";
$label = sprintf('%s %d %s', __('Kandidaat', $domain), $index, $letter);
woocommerce_form_field( $field, array(
'type' => 'text',
'label' => $label,
'placeholder' => '',
'class' => array('custom-field form-row-'.$class),
'required' => true, // or false
), WC()->checkout->get_value( $field ) );
}
}
}
echo '</div></div>';
}
}
// Validate custom fields
add_action( 'woocommerce_after_checkout_validation', 'validate_custom_checkout_fields', 10, 2 );
function validate_custom_checkout_fields( $data, $errors ) {
if ( did_action('woocommerce_after_checkout_validation') >= 2 ) return;
$item_qty = get_specific_cart_item_quantity();
if ( $item_qty ) {
$domain = 'woocommerce';
$break = false;
// 1st Loop (Letters)
foreach ( get_candidate_fields_labels() as $label ) {
$key = strtolower($label);
// 2nd Loop (Numbers)
for ( $i = 1; $i <= $item_qty; $i++ ) {
$field = "custom_field_{$key}{$i}";
if ( isset($_POST[$field]) && empty($_POST[$field]) ) {
$errors->add( 'validation', __('Vul a.u.b. de verplichte velden in.', $domain), 'error' );
$break = true;
break;
}
}
if ( $break ) break;
}
}
}
// Save custom field data as custom order meta data
add_action( 'woocommerce_checkout_create_order', 'save_custom_checkout_fields', 10, 2 );
function save_custom_checkout_fields( $order, $data ) {
$item_qty = get_specific_cart_item_quantity();
if ( $item_qty ) {
// 1st Loop (Letters)
foreach ( get_candidate_fields_labels() as $label ) {
$key = strtolower($label);
// 2nd Loop (Numbers)
for ( $i = 1; $i <= $item_qty; $i++ ) {
$field = "custom_field_{$key}{$i}";
if ( isset($_POST[$field]) && ! empty($_POST[$field]) ) {
$order->update_meta_data( $field, sanitize_text_field($_POST[$field]) );
}
}
}
$order->update_meta_data( 'participants', $item_qty ); // Add the number of participants
}
}
// Display custom fields data on email notifications
add_action( 'woocommerce_email_order_details', 'display_on_email_notifications', 20, 4 );
function display_on_email_notifications( $order, $sent_to_admin, $plain_text, $email ) {
$item_qty = $order->get_meta('participants');
// Targeting "New order" and "Customer completed order" email notifications
if ( $item_qty > 0 && in_array($email->id, ['new_order','customer_completed_order']) ) {
$domain = 'woocommerce';
echo '<style>
.personal-info table{width: 100%; font-family: \'Helvetica Neue\', Helvetica, Roboto, Arial, sans-serif;
color: #737373; border: 1px solid #e4e4e4; margin-bottom:8px;}
.personal-info table th, .personal-info table td{text-align: left; border-top-width: 4px; color: #737373;
border: 1px solid #e4e4e4; padding: 12px; width:'.($item_qty == 1 ? '100%' : '50%').';}
.personal-info table td h4{font-size:92%; margin-block-start: 0; margin-block-end: 1em;}
.personal-info table td p{font-size:84%; line-height:20px; margin:0 !important;}
</style>';
echo '<div class="personal-info">
<h3>' . __('<b>Persoonsgegevens BHV</b>', $domain) . '</h3>
<p>' . __('Vul a.u.b. de persoonsgegevens van de BHV kandidaten in hieronder.', $domain) . '</p>
<table cellspacing="0" cellpadding="6"><tbody>
<tr>';
for ( $i = 1; $i <= $item_qty; $i++ ) {
echo '<td>';
printf('<h4>%s %d</h4><p>', __('Kandidaat', $domain), $i);
// 2nd Loop (letters)
foreach ( get_candidate_fields_labels() as $label ) {
$key = strtolower($label);
$field = "custom_field_{$key}{$i}";
printf('<strong>%s:</strong> %s<br>', $label, $order->get_meta($field));
}
echo '</p></td>';
echo $i % 2 == 0 && $i < $item_qty ? '</tr><tr>' : '';
echo $item_qty % 2 != 0 && $i == $item_qty ? '<td><h4> </h4><p> </p></td>' : '';
}
echo '</tr></tbody></table></div><br>';
}
}
The participant(s) custom fields data will be displayed in 2 columns, a bit like in checkout.
Code goes in functions.php file of your child theme (or in a plugin). Tested and works.