get_post_meta in woocommerce email notifications - wordpress

I'm trying to get some data from an order in a woocommerce email template, but get_post_meta just returns false. This code works on the thankyou page. I have spent too much time on this. Any help would be appreciated. Thanks!
global $post;
echo "test!!!<br />";
$x = get_post_meta( $order->id, 'attendee_data', true );
$y = get_post_meta( $order->id, 'attendee_test', true );
echo $order->id . '<br />';
echo $x;
echo $y;
I've attached a picture of the sql as well as an email.
SQL: http://i.stack.imgur.com/zUFBa.png
Email: http://i.stack.imgur.com/Uqtih.png
The whole email template:
<?php do_action('woocommerce_email_header', $email_heading); ?>
<p><?php _e( "Your order has been received and is now being processed. Your order details are shown below for your reference:", 'woocommerce' ); ?></p>
<?php do_action( 'woocommerce_email_before_order_table', $order, $sent_to_admin, $plain_text ); ?>
<h2><?php echo __( 'Order:', 'woocommerce' ) . ' ' . $order->get_order_number(); ?></h2>
<table cellspacing="0" cellpadding="6" style="width: 100%; border: 1px solid #eee;" border="1" bordercolor="#eee">
<thead>
<tr>
<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php echo $order->email_order_items_table( $order->is_download_permitted(), true, ( $order->status=='processing' ) ? true : false ); ?>
</tbody>
<tfoot>
<?php
if ( $totals = $order->get_order_item_totals() ) {
$i = 0;
foreach ( $totals as $total ) {
$i++;
?><tr>
<th scope="row" colspan="2" style="text-align:left; border: 1px solid #eee; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td style="text-align:left; border: 1px solid #eee; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
</tr><?php
}
}
?>
</tfoot>
</table>
<?php
global $post;
echo "test!!!<br />";
$x = get_post_meta( $order->id, 'attendee_data', true );
$y = get_post_meta( $order->id, 'attendee_test', true );
echo $order->id . '<br />';
echo $x;
echo $y;
foreach ( $x as $k => $p ) {
echo $k ." ... ". $p;
} ?>
<?php // attendee_order_details($order->get_order_number()) ?>
<?php do_action( 'woocommerce_email_after_order_table', $order, $sent_to_admin, $plain_text ); ?>
<?php do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text ); ?>
<h2><?php _e( 'Customer details', 'woocommerce' ); ?></h2>
<?php if ($order->billing_email) : ?>
<p><strong><?php _e( 'Email:', 'woocommerce' ); ?></strong> <?php echo $order->billing_email; ?></p>
<?php endif; ?>
<?php if ($order->billing_phone) : ?>
<p><strong><?php _e( 'Tel:', 'woocommerce' ); ?></strong> <?php echo $order->billing_phone; ?></p>
<?php endif; ?>
<?php wc_get_template( 'emails/email-addresses.php', array( 'order' => $order ) ); ?>
<?php do_action( 'woocommerce_email_footer' ); ?>

I did some testing based on your info and tried to reproduce your problems.
First I created a function which inserts the post meta (attendee_test and attendee_data) when placing an order (using the woocommerce_checkout_update_order_meta hook like you do).
I added this in my themes functions.php (Note that the values are based on your input (image from db) and are not dynamic, just for testing):
add_action('woocommerce_checkout_update_order_meta', 'add_meta_values', 2);
function add_meta_values($order_id){
// array with attendee data
$attendee_data = array(
array(
'edit' => 'false',
'company' => 'get',
)
);
add_post_meta( $order_id, 'attendee_data', $attendee_data );
add_post_meta( $order_id, 'attendee_test', 'test' );
}
Then I added the following code to the template customer-processing-order.php:
<?php
$attendee_data = get_post_meta( $order->id, 'attendee_data', true );
$attendee_test = get_post_meta( $order->id, 'attendee_test', true );
echo 'Order ID: ' . $order->id . '<br />';
echo 'Attendee Test: ' . $attendee_test . '<br />';
echo 'Attendee Data:<br />';
foreach ( $attendee_data as $k => $data ) {
foreach ($data as $key => $value){
echo $key . ' .. ' . $value . '<br />';
}
} ?>
As you can see I modified it a bit to make it more clear. Also changed the $attendee_data loop because I think that wasn't completely right (needed an extra foreach). Of course this isn't related to the real problem.
Making a testorder will show the following data in the email:
This result demonstrate that get_post_meta is working in the email template based on the code above. (I used Wordpress 4.0.1 and WooCommerce 2.2.10).
If the test above is working fine also in your case then I think that the values are inserted in your database after the email is sent (they are inserted right, but to late).
Another thing you might want to check is resending the confirmation email. You can do this from the Wordpress admin. When you edit an order you have a dropdown 'Actions' on the right side. You can select 'Processing order' under 'Resend order emails'. Then click the refresh icon next to the dropdown and you will receive the order confirmation email again. See screenshot below:
This time you know for sure the values are already in the database before you're sending the email.
Hope this information is helping you to solve the problem.

Well, 'attendee_data' is a serialized object so the third argument passed on the function get_post_meta must be set to false (or omitted).
$x = get_post_meta( $order->id, 'attendee_data', false );

Related

Can't show the product name on table using get_name();

I can't echo the product name on my order page. I'm using ultimate member plugin with WooCommerce. "get_id();" is working just fine. I used "$order->get_name()" to echo the ordered product name. but it shows me error when tried to load the page.
<tbody>
<?php
foreach( $customer_orders as $customer_order ) {
$order = wc_get_order( $customer_order->ID );
$order_id = $customer_order->ID;
$order_data = $order->get_data();
$order_date = strtotime( $order->get_date_created() );
?>
<tr class="order" data-order_id="<?php echo esc_attr( $order_id ); ?>">
<?php do_action( 'um_woocommerce_orders_tab_before_table_row', $order, $customer_orders ); ?>
<td class="order-total" data-title="<?php _e( 'Item', 'um-woocommerce' ); ?>">
<?php echo $order->get_name() ?></td>
<td class="order-date" data-title="<?php _e( 'Date', 'um-woocommerce' ); ?>">
<time
datetime="<?php echo wp_date( 'Y-m-d', $order_date ); ?>"><?php echo wp_date( $date_time_format, $order_date ); ?></time>
</td>
<td class="order-status" data-title="<?php _e( 'Status', 'um-woocommerce' ); ?>">
<span
class="um-woo-status <?php echo $order->get_status(); ?>"><?php echo wc_get_order_status_name( $order->get_status() ); ?></span>
</td>
<td class="order-total" data-title="<?php _e( 'Total', 'um-woocommerce' ); ?>">
<?php echo $order->get_formatted_order_total() ?></td>
<td class="order-detail">
<a href="<?php echo esc_url( "$url#$order_id" ); ?>" class="um-woo-view-order um-tip-n"
title="<?php esc_attr_e( 'View order', 'um-woocommerce' ); ?>"><i class="um-icon-eye"></i></a>
<?php do_action( 'um_woocommerce_orders_tab_actions', $order, $customer_orders ); ?>
</td>
<?php
if ( UM()->options()->get('woo_account_order_ations') ) {
$actions = wc_get_account_orders_actions( $order );
echo '<td class="order-actions">';
if ( !empty( $actions ) ) {
foreach ( $actions as $key => $action ) {
echo '' . esc_html( $action['name'] ) . '';
}
}
echo '</td>';
}
?>
<?php do_action( 'um_woocommerce_orders_tab_after_table_row', $order, $customer_orders ); ?>
</tr>
<?php } ?>
</tbody>
There is no get_name() function for order object. You need loop through the order items to get the product object and use the $product->get_name() function
<?php foreach ($order->get_items() as $item_key => $item) {
$product = $item->get_product();
?>
<td class="order-total" data-title="<?php _e( 'Item', 'um-woocommerce' ); ?>">
<?php echo $product->get_name() ?>
</td>
<?php } ?>

WordPress WooCommerce add new field in each row at /my-account/subscriptions/ page

I am using WordPress with WooCommerce and WooCommerce subscriptions plugins and below is my code in which I have added a custom field called (Mindesk VAR Client User - Dropdown) to show in "Edit Subscription" admin page saving to my custom field based on subscription ID.
This is how it's looking like.
And this is my working code.
<?php
// action triggered when we go to add/edit subscription page
add_action('woocommerce_admin_order_data_after_order_details', 'showWCSubscriptionCustomFields');
add_action('woocommerce_process_shop_order_meta', 'saveWCSubscriptionCustomFields');
function showWCSubscriptionCustomFields($subscription) {
$currentPage = get_current_screen();
// If page is "Edit Subscription" page, then only show
if ($currentPage->action == 'add')
return;
// Getting all the users
$mindeskUsers = getAllUsers();
?>
<br class="clear" />
<p class="form-field form-field-wide">
<label for="mindesk_wc_subscriptions_var_client_user_id">Mindesk VAR Client User:</label>
<?php
$selectedUser = get_post_meta($subscription->get_id(), 'mindesk_wc_subscriptions_var_client_user_id', true);
echo getUsersListSelect('mindesk_wc_subscriptions_var_client_user_id', $selectedUser, $mindeskUsers, 'mindesk_select2');
?>
</p>
<?php
}
function saveWCSubscriptionCustomFields($subscription_id) {
// wc_clean() and wc_sanitize_textarea() are WooCommerce sanitization functions
update_post_meta($subscription_id, 'mindesk_wc_subscriptions_var_client_user_id', wc_clean($_POST['mindesk_wc_subscriptions_var_client_user_id']));
}
This is working fine for me.
Now I have a custom requirement to add a button something called as Transfer in each row in http:://www.mywebsite.com/my-account/subscriptions/ page.
For example this page somewhere beside Total.
After clicking on that button, the popup should come with a form and I should be able to save a field "Transfer to VAR Client User" based on subscription ID same as I have shown you a working code above with my custom field.
I have tried to do R & D but most of the links suggesting to add custom fields and all in "My Account" page (/my-account) But I want to achieve the same in "my-account/subscriptions" page.
Can anyone guide me how can I achieve this? Any suggestion will be highly appreciated.
Thanks
You can copy the my-subscriptions.php file from the woocommerce-subscriptions/templates/myaccount and add it to your active theme woocommerce folder create folder myaccount and paste my-subscriptions.php. and then modify as per your requirement.
<?php if ( ! empty( $subscriptions ) ) : ?>
<table class="my_account_subscriptions my_account_orders woocommerce-orders-table woocommerce-MyAccount-subscriptions shop_table shop_table_responsive woocommerce-orders-table--subscriptions">
<thead>
<tr>
<th class="subscription-id order-number woocommerce-orders-table__header woocommerce-orders-table__header-order-number woocommerce-orders-table__header-subscription-id"><span class="nobr"><?php esc_html_e( 'Subscription', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-status order-status woocommerce-orders-table__header woocommerce-orders-table__header-order-status woocommerce-orders-table__header-subscription-status"><span class="nobr"><?php esc_html_e( 'Status', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-next-payment order-date woocommerce-orders-table__header woocommerce-orders-table__header-order-date woocommerce-orders-table__header-subscription-next-payment"><span class="nobr"><?php echo esc_html_x( 'Next payment', 'table heading', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-total order-total woocommerce-orders-table__header woocommerce-orders-table__header-order-total woocommerce-orders-table__header-subscription-total"><span class="nobr"><?php echo esc_html_x( 'Total', 'table heading', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-total order-total woocommerce-orders-table__header woocommerce-orders-table__header-order-total woocommerce-orders-table__header-subscription-total"><span class="nobr"><?php echo esc_html_x( 'Transfer', 'table heading', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-actions order-actions woocommerce-orders-table__header woocommerce-orders-table__header-order-actions woocommerce-orders-table__header-subscription-actions"> </th>
</tr>
</thead>
<tbody>
<?php /** #var WC_Subscription $subscription */ ?>
<?php foreach ( $subscriptions as $subscription_id => $subscription ) : ?>
<tr class="order woocommerce-orders-table__row woocommerce-orders-table__row--status-<?php echo esc_attr( $subscription->get_status() ); ?>">
<td class="subscription-id order-number woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-id woocommerce-orders-table__cell-order-number" data-title="<?php esc_attr_e( 'ID', 'woocommerce-subscriptions' ); ?>">
<?php echo esc_html( sprintf( _x( '#%s', 'hash before order number', 'woocommerce-subscriptions' ), $subscription->get_order_number() ) ); ?>
<?php do_action( 'woocommerce_my_subscriptions_after_subscription_id', $subscription ); ?>
</td>
<td class="subscription-status order-status woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-status woocommerce-orders-table__cell-order-status" data-title="<?php esc_attr_e( 'Status', 'woocommerce-subscriptions' ); ?>">
<?php echo esc_attr( wcs_get_subscription_status_name( $subscription->get_status() ) ); ?>
</td>
<td class="subscription-next-payment order-date woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-next-payment woocommerce-orders-table__cell-order-date" data-title="<?php echo esc_attr_x( 'Next Payment', 'table heading', 'woocommerce-subscriptions' ); ?>">
<?php echo esc_attr( $subscription->get_date_to_display( 'next_payment' ) ); ?>
<?php if ( ! $subscription->is_manual() && $subscription->has_status( 'active' ) && $subscription->get_time( 'next_payment' ) > 0 ) : ?>
<br/><small><?php echo esc_attr( $subscription->get_payment_method_to_display( 'customer' ) ); ?></small>
<?php endif; ?>
</td>
<td class="subscription-total order-total woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-total woocommerce-orders-table__cell-order-total" data-title="<?php echo esc_attr_x( 'Total', 'Used in data attribute. Escaped', 'woocommerce-subscriptions' ); ?>">
<?php echo wp_kses_post( $subscription->get_formatted_order_total() ); ?>
</td>
<td class="subscription-actions order-actions woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-actions woocommerce-orders-table__cell-order-actions">
<?php echo esc_html_x( 'Transfer', 'Transfer a subscription', 'woocommerce-subscriptions' ); ?>
</td>
<td class="subscription-actions order-actions woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-actions woocommerce-orders-table__cell-order-actions">
<?php echo esc_html_x( 'View', 'view a subscription', 'woocommerce-subscriptions' ); ?>
<?php do_action( 'woocommerce_my_subscriptions_actions', $subscription ); ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php if ( 1 < $max_num_pages ) : ?>
<div class="woocommerce-pagination woocommerce-pagination--without-numbers woocommerce-Pagination">
<?php if ( 1 !== $current_page ) : ?>
<a class="woocommerce-button woocommerce-button--previous woocommerce-Button woocommerce-Button--previous button" href="<?php echo esc_url( wc_get_endpoint_url( 'subscriptions', $current_page - 1 ) ); ?>"><?php esc_html_e( 'Previous', 'woocommerce-subscriptions' ); ?></a>
<?php endif; ?>
<?php if ( intval( $max_num_pages ) !== $current_page ) : ?>
<a class="woocommerce-button woocommerce-button--next woocommerce-Button woocommerce-Button--next button" href="<?php echo esc_url( wc_get_endpoint_url( 'subscriptions', $current_page + 1 ) ); ?>"><?php esc_html_e( 'Next', 'woocommerce-subscriptions' ); ?></a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php else : ?>
<p class="no_subscriptions woocommerce-message woocommerce-message--info woocommerce-Message woocommerce-Message--info woocommerce-info">
<?php if ( 1 < $current_page ) :
printf( esc_html__( 'You have reached the end of subscriptions. Go to the %sfirst page%s.', 'woocommerce-subscriptions' ), '', '' );
else :
esc_html_e( 'You have no active subscriptions.', 'woocommerce-subscriptions' );
?>
<a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>">
<?php esc_html_e( 'Browse products', 'woocommerce-subscriptions' ); ?>
</a>
<?php
endif; ?>
</p>
<?php endif; ?>
Tested and works

If there is no discount hide table row in Woocommerce

I am trying to implement the code below when a discount is applied to an order on my Woocommerce store. Right now, it shows every time a product is added. I am discounting all orders 15% when 5 or more products are added to the cart. But if I only add 2 products the table row still shows (and it shows $40 which is odd). It works great when 5 or more items are added to the cart. Any help would be much appreciated.
<tr class="cart-subtotal">
<th><?php esc_html_e( '15% Discount', 'beaux' ); ?></th>
<td><?php esc_html_e( '-', 'beaux' ); ?><?php echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); ?></td>
</tr>
I think you did it using woocommerce templates, it's better to use hooks:
add_filter( 'woocommerce_cart_totals_order_total_html', 'ywp_custom_total_message_html' );
function ywp_custom_total_message_html( $value ) {
global $woocommerce;
$cart_item_count = $woocommerce->cart->cart_contents_count;
if( $cart_item_count >= 5 ) {
$value .= esc_html_e( '15% Discount', 'beaux' ) . '<br />';
}
return $value;
}
Code goes in functions.php of your active theme/child theme. Tested and works.
You can check the number of items in the cart using WC()->cart->get_cart_contents_count().
<?php if ( WC()->cart->get_cart_contents_count() >= 5 ): ?>
<tr class="cart-subtotal">
<th><?php esc_html_e( '15% Discount', 'beaux' ); ?></th>
<td><?php esc_html_e( '-', 'beaux' ); ?><?php echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); ?></td>
</tr>
<?php endif; ?>
Just replace your snippet by this one. If less than 5 items are in the cart, the discount won't show.

WordPress custom user_meta not saving

I have built a custom plugin and I need to be able to add custom meta to the user profile screen.
I have the meta showing but they don't seem to update. This is the first instance of this meta so it doesn't exist in the DB already.
The files are located in my plugin dir and not in my theme.
<?php
add_action( 'show_user_profile', 'add_extra_social_links' );
add_action( 'edit_user_profile', 'add_extra_social_links' );
function add_extra_social_links( $user )
{
?>
<h3>Web App Information</h3>
<table class="form-table">
<tr>
<th><label for="companyname">Company Name</label></th>
<td>
<?php
$args = array(
'post_type' => array('operators','clients'),
'posts_per_page' => -1,
'orderby' => 'title',
);
$myposts = get_posts( $args );
echo '<select id="companyname"name="companyname">';
echo '<option value="' . esc_attr(get_the_author_meta( 'companyname', $user->ID )) . '">';
foreach ( $myposts as $post ) : setup_postdata( $post ); ?>
<option value="<?php echo $post->post_title; ?>">
<?php echo $post->post_title; ?>
</option>
<?php endforeach;
echo '</select>';
wp_reset_postdata();?>
</td>
</tr>
<tr>
<th><label for="companyadmin">Is this user a company admin.</label></th>
<td>
<?php
echo '<select id="companyadmin" name="companyadmin">';
echo '<option value="' . esc_attr(get_the_author_meta( 'companyadmin', $user->ID )) . '">';
echo '<option value="Y">Yes, is admin.</option>';
echo '<option value="N">No, is not admin.</option>';
echo '</select>';
?>
</td>
</tr>
</table>
<?php
}
add_action( 'personal_options_update', 'save_extra_social_links' );
add_action( 'edit_user_profile_update', 'save_extra_social_links' );
function save_extra_social_links( $user_id )
{
update_user_meta( $user_id,'companyname', $_POST['companyname'] );
update_user_meta( $user_id,'companyadmin', $_POST['companyadmin'] );
}
?>
try use function get_current_user_id in $user_id
i think you use parameter but not send in hook

How to arrange the custom field on woocommerce checkout page

I know how to add a custom field to the checkout page, and then how to process the field also.
But when I add a custom field to my form, it always appears at the end of the form. How can I make it appear on top of other fields?
My current script:
<?php *// Add a new checkout field
function kia_filter_checkout_fields($fields){
$fields['extra_fields'] = array(
'message_field' => array(
'type' => 'textarea',
'required' => true,
'label' => __( 'Message Field' )
),
);
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'kia_filter_checkout_fields' );
// display the extra field on the checkout form
function kia_extra_checkout_fields(){
$checkout = WC()->checkout(); ?>
<div class="extra-fields">
<h3><?php _e( 'WRITE A MESSAGE TO RECIPIENT' ); ?><span>(<?php _e( 'Leave blank if not required' ); ?>)</span></h3>
<?php
// because of this foreach, everything added to the array in the previous function will display automagically
foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) : ?>
<?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
<?php endforeach; ?>
</div>
<?php }
add_action( 'woocommerce_checkout_after_customer_details' ,'kia_extra_checkout_fields' );
// save the extra field when checkout is processed
function kia_save_extra_checkout_fields( $order_id, $posted ){
// don't forget appropriate sanitization if you are using a different field type
if( isset( $posted['message_field'] ) ) {
update_post_meta( $order_id, '_message_field', sanitize_text_field( $posted['message_field'] ) );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'kia_save_extra_checkout_fields', 10, 1);
// display the extra data on order recieved page and my-account order review
function kia_display_order_data( $order_id ){ ?>
<h2><?php _e( 'Additional Info' ); ?></h2>
<table class="shop_table shop_table_responsive additional_info">
<tbody>
<tr>
<th><?php _e( 'message_field:' ); ?></th>
<td><?php echo get_post_meta( $order_id, '_message_field', true ); ?></td>
</tr>
<tr>
</tr>
</tbody>
</table>
<?php }
add_action( 'woocommerce_thankyou', 'kia_display_order_data', 20 );
add_action( 'woocommerce_view_order', 'kia_display_order_data', 20 );
// display the extra data in the order admin panel
function kia_display_order_data_in_admin( $order ){ ?>
<div class="order_data_column">
<h4><?php _e( 'Extra Details', 'woocommerce' ); ?></h4>
<?php
echo '<p><strong>' . __( 'Some field' ) . ':</strong>' . get_post_meta( $order->id, '_message_field', true ) . '</p>';
// echo '<p><strong>' . __( 'Another field' ) . ':</strong>' . get_post_meta( $order->id, '_another_field', true ) . '</p>'; ?>
</div>
<?php }
add_action( 'woocommerce_admin_order_data_after_order_details', 'kia_display_order_data_in_admin' );
?>*
Instead of hooking into woocommerce_checkout_after_customer_details you need to hook into woocommerce_checkout_before_customer_details, that way your custom field will appear on top of other fields.
So change the following line of code
add_action( 'woocommerce_checkout_after_customer_details' ,'kia_extra_checkout_fields' );
to
add_action( 'woocommerce_checkout_before_customer_details' ,'kia_extra_checkout_fields' );
Please try to remove class="extra-fields"
<div id="my_custom_checkout_field">
<h3><?php _e( 'WRITE A MESSAGE TO RECIPIENT' ); ?><span>(<?php _e( 'Leave blank if not required' ); ?>)</span></h3>
<?php
// because of this foreach, everything added to the array in the previous function will display automagically
foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) : ?>
<?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?>
<?php endforeach; ?>
</div>
I have used it with id and it works well for me. Like this

Resources