Reputation: 67
In woocommerce I have added custom fields on checkout page based on cart count.
// Adding Custom Fields based on Cart Count
add_action( 'woocommerce_before_checkout_billing_form', 'srd_custom_einstiegswahl');
function srd_custom_einstiegswahl($checkout){
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$i = 1;
foreach($items as $item => $values) {
$_product = $values['data']->post;
$quantity = $values['quantity'];
$x = 1;
while ($x <= $quantity) {
// Add fields here
echo '<h6>Reiseteilnehmer '.$x . '</h6>';
woocommerce_form_field( 'attendee_surname_'.$x, array(
'type' => 'text',
'class' => array('checkout_vorname'),
'label' => __('Vorame'),
'placeholder' => __(''),
'required' => true
), $checkout->get_value( 'attendee_surname_'.$x ));
woocommerce_form_field( 'attendee_name_'.$x, array(
'type' => 'text',
'class' => array('checkout_nachname'),
'label' => __('Nachname'),
'placeholder' => __(''),
'required' => true
), $checkout->get_value( 'attendee_name_'.$x ));
echo '<select name=einstiegswahl'.$x .'>';
// Select field populated by Custom Product Meta
echo '<option value="" style="display:none"> Bitte wählen Sie Ihren Einstiegsort </option>';
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
// Get the custom field data
$einstiegsorte = get_post_meta( $cart_item[ 'product_id' ], '_einstiegsorte', true );
if( ! empty($einstiegsorte) ){
// if it's multiline we split it in an array
$select_field_items = explode( "\n", $einstiegsorte );
// If the array has more than one item
if( sizeof( $select_field_items ) > 1 ){
foreach( $select_field_items as $value )
echo '<option value="'. $value .'">' . $value . '</option>';
}
// If there is only one line
else {
// we clean it
$value = str_replace('\n', '', $einstiegsorte);
echo '<option value="'. $value .'">' . $value . '</option>';
}
}
}
echo '</select>'; $checkout->get_value( 'einstiegswahl'.$x );
$x++;
}
$i++;
}
}
// Process the checkout
add_action('woocommerce_checkout_process', 'srd_teilnehmer_fields_process');
function srd_teilnehmer_fields_process() {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$i = 1;
foreach($items as $item => $values) {
$_product = $values['data']->post;
$quantity = $values['quantity'];
$x = 1;
for($x = 1; $x <= $quantity; $x++ ) {
//while ($x <= $quantity) {
if (!$_POST['attendee_surname_'.$x] || !$_POST['attendee_name_'.$x] || !$_POST['einstiegswahl'.$x]) wc_add_notice( __( 'Bitte wählen Sie Ihren Einstiegsort', 'woocommerce' ), 'error' );
}
}
}
// Update the order meta with field value
add_action('woocommerce_checkout_update_order_meta', 'srd_teilnehmer_update_order_meta');
function srd_teilnehmer_update_order_meta( $order_id ) {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$i = 1;
foreach($items as $item => $values) {
$_product = $values['data']->post;
$quantity = $values['quantity'];
$x = 1;
for($x = 1; $x <= $quantity; $x++ ) {
if ( $_POST['attendee_name_'.$x] ) update_post_meta( $order_id, 'attendee_surname_'.$x , sanitize_text_field($_POST['attendee_name_'.$x]) );
if ($_POST['attendee_surname_'.$x]) update_post_meta( $order_id, 'attendee_name_'.$x, esc_attr($_POST['attendee_surname_'.$x]));
if ($_POST['einstiegswahl'.$x]) update_post_meta( $order_id, ' Teilnehmer Einstiegsort' .$x, esc_attr($_POST['einstiegswahl'.$x]));
}}}
All works fine and fields get validated and saved.
The problem: I am not able to get and display the values in admin Order edit pages.
Since I do not know at this point how many fields were created based on the amount ordered, I first need to get the a number of ordered items.
Here is that related code:
add_action( 'woocommerce_admin_order_data_after_billing_address', 'srd_teilnehmer_checkout_field_display_admin_order_meta', 10, 1 );
//add_action( 'woocommerce_email_order_meta', 'srd_teilnehmer_checkout_field_display_admin_order_meta', 10, 3 );
function srd_teilnehmer_checkout_field_display_admin_order_meta($order) {
$order = wc_get_order( $order_id );
$items = $item_data->get_quantity();
foreach($items as $item => $values) {
$order_quantity = $values['quantity'];
$x = 1;
while ($x <= $order_quantity) {
echo '<p><strong>'.__('Nachname'.$x).':</strong> ' . get_post_meta( $order->id, 'attendee_name_'.$x, true ) . '</p>';
}
}}
How can I get and display those custom field values in admin Order edit pages?
How to display that custom field values in email notifications?
Any help will be appreciated.
Upvotes: 0
Views: 764
Reputation: 253824
You are complicating a little bit things and there is some mistakes in your code.
It should be much better to display the attendees booking data as a custom meta box in admin shop orders edit pages (Here on the right column).
So I have completely revisited your code:
// Adding Custom Fields based on Cart Count
add_action( 'woocommerce_before_checkout_billing_form', 'srd_custom_einstiegswahl');
function srd_custom_einstiegswahl( $checkout ){
$count = 1;
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
$options = array( '' => __("Bitte wählen Sie Ihren Einstiegsort") );
$einstiegsorte = get_post_meta( $cart_item[ 'product_id' ], '_einstiegsorte', true );
if( ! empty($einstiegsorte) ){
$option_items = explode( "\n", $einstiegsorte );
if( sizeof( $option_items ) > 1 ){
foreach( $option_items as $value )
$options[$value] = $value;
} else {
$value = str_replace('\n', '', $einstiegsorte);
$options[$value] = $value;
}
}
// Loop through cart item quantity
for($i = 1; $i <= $cart_item['quantity']; $i++ ) {
$j = $count.'_'.$i;
echo '<h6>Reiseteilnehmer '.$i . '</h6>';
woocommerce_form_field( '_teilnehmer_vorame_'.$j, array(
'type' => 'text',
'class' => array('checkout_vorname'),
'label' => __('Vorame'),
'required' => true,
), $checkout->get_value( '_teilnehmer_vorame_'.$j ));
woocommerce_form_field( '_teilnehmer_nachname_'.$j, array(
'type' => 'text',
'class' => array('checkout_nachname'),
'label' => __('Nachname'),
'required' => true,
), $checkout->get_value( '_teilnehmer_nachname_'.$j ));
woocommerce_form_field( '_teilnehmer_einstiegswahl_'.$j, array(
'type' => 'select',
'class' => array('checkout_einstiegswahl'),
'label' => __('Einstiegswahl'),
'required' => true,
'options' => $options,
), $checkout->get_value( '_teilnehmer_einstiegswahl_'.$j ));
}
$count++;
}
}
// Custom checkout fields validation
add_action('woocommerce_checkout_process', 'srd_teilnehmer_fields_process');
function srd_teilnehmer_fields_process() {
$count = 1;
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
// Loop through cart item quantity
for($i = 1; $i <= $cart_item['quantity']; $i++ ) {
$j = $count.'_'.$i;
if (!$_POST['_teilnehmer_vorame_'.$j] || !$_POST['_teilnehmer_nachname_'.$j] || !$_POST['_teilnehmer_einstiegswahl_'.$j])
wc_add_notice( __( 'Bitte wählen Sie Ihren Einstiegsort', 'woocommerce' ), 'error' );
}
$count++;
}
}
// Update the order meta data with checkout custom fields values
add_action('woocommerce_checkout_create_order', 'srd_teilnehmer_checkout_create_order', 20, 2 );
function srd_teilnehmer_checkout_create_order( $order, $data ) {
$count = 1;
// Loop through cart item quantity
foreach( WC()->cart->get_cart() as $cart_item ) {
// Loop through item quantity
for($i = 1; $i <= $cart_item['quantity']; $i++ ) {
$j = $count.'_'.$i;
if ( isset($_POST['_teilnehmer_vorame_'.$j]) )
$order->update_meta_data( '_teilnehmer_vorame_'.$j , sanitize_text_field($_POST['_teilnehmer_vorame_'.$j]) );
if ( isset($_POST['_teilnehmer_nachname_'.$j]) )
$order->update_meta_data( '_teilnehmer_nachname_'.$j, sanitize_text_field($_POST['_teilnehmer_nachname_'.$j]) );
if ( isset($_POST['_teilnehmer_einstiegswahl_'.$j]) )
$order->update_meta_data( '_teilnehmer_einstiegswahl_'.$j, sanitize_text_field($_POST['_teilnehmer_einstiegswahl_'.$j]) );
}
$count++;
}
}
// Adding Custom metabox in admin orders edit pages (on the right column)
add_action( 'add_meta_boxes', 'add_reiseteilnehmer_metabox' );
function add_reiseteilnehmer_metabox(){
add_meta_box(
'attendees',
__('Reiseteilnehmer'),
'reiseteilnehmer_inhalt',
'shop_order',
'side', // or 'normal'
'default' // or 'high'
);
}
// Adding the content for the custom metabox
function reiseteilnehmer_inhalt() {
$order = wc_get_order(get_the_id());
$count = 1;
$key_labels = array( 'vorame', 'nachname', 'einstiegswahl' );
// Loop through order items
foreach ( $order->get_items() as $item ){
echo '<h4 style="margin:1em 0 .5em;">Order item '.$count.'</h4>';
// Loop through item quantity
for($i = 1; $i <= $item->get_quantity(); $i++ ) {
echo '<div style="background-color:#eee;padding:2px;margin-bottom:.4em;">
<h4 style="margin:.5em 0;padding:2px;">Reiseteilnehmer '.$i.'</h4>
<table style="text-align:left;margin-bottom:.7em;" cellpadding="2"><tbody>';
$style = ' style="padding:2px 0;"';
// Loop through attendee fields
foreach( $key_labels as $key ){
$value = get_post_meta( $order->get_id(), '_teilnehmer_'.$key.'_'.$count.'_'.$i, true );
echo '<tr><th>'.ucfirst($key).':</th><td>'.$value.'</td></tr>';
}
echo '</tbody></table></div>';
}
$count++;
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
To display that in emails and in front end "Order Received" and My account "Order view" pages, you will have to ask a new question as it is just too broad to be answered in one answer.
Upvotes: 2