I have the function in functions.php:
// Hook in
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['billing']['billing_infos'] = array(
'type' => 'textarea',
'label' => __('Podaj NIP', 'woocommerce'),
'placeholder' => _x('Tutaj możesz wpisać NIP', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
This code is adding custom field to billing form. It's working fine because I see it when I make an order like normal user. The problem is with data from this field in admin panel. I can't see it. Any help on this please?
This missing hooked function will display your custom fields in Order edit page, below Billing details:
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_billing_infos_to_admin_order_meta', 20, 1 );
function display_billing_infos_to_admin_order_meta( $order ){
echo '<p><strong>'.__('Podaj NIP').':</strong> ' . get_post_meta( $order->get_id(), '_billing_infos', true ) . '</p>';
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Related
UPDATE:
I used the following code from here and it is fixed. The custom billing field is showing up in the backend and e-mails. Seemed like I needed to save the data to meta. Strange this isn't described on woocommerce's own documentation. Hope some else benefits from it too.
I've added some custom date fields to my checkout page. They are showing and I can input dates. But the input isn't showing in my admin order page or in de emails. I've searched some topics, but can't figure it out. I've followed this instruction under 'Adding Custom Shipping And Billing Fields'. I only see the label at the oder edit page and not the value. What is wrong here?
I only tried it with de 'date_from' field for testing purpose. 'date_till' also needs to be shown.
Code I got:
// Hook in
add_filter( 'woocommerce_checkout_fields' , 'custom_new_checkout_fields_date_from' );
// Our hooked in function – $fields is passed via the filter!
function custom_new_checkout_fields_date_from( $newDateFrom ) {
$newDateFrom['billing']['date_from'] = array(
'type' => 'date',
'label' => __('Datum huur vanaf', 'woocommerce'),
'placeholder' => _x('Datum huur vanaf', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide'),
'clear' => true
);
return $newDateFrom;
}
// Datum tot veld
// Hook in
add_filter( 'woocommerce_checkout_fields' , 'custom_new_checkout_fields_date_till' );
// Our hooked in function – $fields is passed via the filter!
function custom_new_checkout_fields_date_till( $newDateTill ) {
$newDateTill['billing']['date_till'] = array(
'type' => 'date',
'label' => __('Datum huur tot', 'woocommerce'),
'placeholder' => _x('Datum huur tot', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-wide'),
'clear' => true
);
return $newDateTill;
}
/**
* Display field value on the order edit page
*/
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('Datum huur van').':</strong> ' . get_post_meta( $order->get_id(), '_date_from', true ) . '</p>';
}
/**
* Add a custom field (in an order) to the emails
*/
add_filter( 'woocommerce_email_order_meta_fields', 'custom_woocommerce_email_order_meta_fields', 10, 3 );
function custom_woocommerce_email_order_meta_fields( $keys, $sent_to_admin, $order ) {
$keys['_date_from'] = array(
'label' => __( 'Datum huur vanaf' ),
'value' => get_post_meta( $order->id, '_date_from', true ),
);
return $keys;
}
Im looking to find some php code that will allow me to extract information (Name, address etc) from the checkout fields and add it to the order meta data.
Looking for this to be a simple as possible
Ive previously found this code which allows a custom box to be added to the checkout page, and I sort of understand how it works, however I want to capture their name when they type it into the billing first name box. I can seem to grasp how to capture this data and put it into the order meta data, Ive tried shortening the code and editing it a few times but I dont seem to be winning
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['shipping']['shipping_phone'] = array(
'label' => __('Phone', 'woocommerce'),
'placeholder' => _x('Phone', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
/**
* Display field value on the order edit page
*/
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('Phone From Checkout Form').':</strong> ' . get_post_meta( $order->get_id(), '_shipping_phone', true ) . '</p>';
}
/**
* Add the field to the checkout
*/
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );
function my_custom_checkout_field( $checkout ) {
echo '<div id="my_custom_checkout_field"><h2>' . __('My Field') . '</h2>';
woocommerce_form_field( 'my_field_name', array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'label' => __('Fill in this field'),
'placeholder' => __('Enter something'),
), $checkout->get_value( 'my_field_name' ));
echo '</div>';
}
/**
* Process the checkout
*/
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['my_field_name'] )
wc_add_notice( __( 'Please enter something into this new shiny field.' ), 'error' );
}
/**
* Update the order meta with field value
*/
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['my_field_name'] ) ) {
update_post_meta( $order_id, 'My Field', sanitize_text_field( $_POST['my_field_name'] ) );
}
}
I like this and it does work but just not in the way i need it to work. thanks for any and all help
There are some mistakes and missing things in your code… Try the following replacement code instead:
// Add shipping phone (in checkout and My account edit shipping address) and save field value
add_action( 'woocommerce_shipping_fields', 'add_shipping_phone_field' );
function add_shipping_phone_field( $fields ) {
$fields['shipping_phone'] = array(
'label' => __('Phone', 'woocommerce'),
'placeholder' => _x('Phone', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
// Display shipping phone value on the order edit pages under shipping section
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_shipping_phone_in_admin_orders' );
function display_shipping_phone_in_admin_orders( $order ){
$phone_value = $order->get_meta('_shipping_phone');
if ( ! empty($phone_value) ) {
echo '<p><strong>'.__('Shipping phone').':</strong> ' . $phone_value . '</p>';
}
}
// Add a custom checkout field
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );
function my_custom_checkout_field( $checkout ) {
echo '<div id="my_custom_checkout_field"><h2>' . __('My Field') . '</h2>';
woocommerce_form_field( 'my_field_slug', array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'label' => __('My custom field'),
'placeholder' => __('Enter something… '),
'required' => true,
), $checkout->get_value( 'my_field_slug' ) );
echo '</div>';
}
// Validate required checkout fields
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( isset($_POST['my_field_slug']) && empty($_POST['my_field_slug']) ) {
wc_add_notice( __( '"My custom field" is a required field.' ), 'error' );
}
}
// Add custom checkout field value as custom order meta data
add_action( 'woocommerce_checkout_create_order', 'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order ) {
if ( isset($_POST['my_field_slug']) && ! empty($_POST['my_field_slug']) ) {
$order->update_meta_data( 'My Field', sanitize_text_field( $_POST['my_field_slug'] ) );
}
}
// Display "My field" value on the order edit pages under billing section
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_my_custom_checkout_field_in_admin_orders', 10, 1 );
function display_my_custom_checkout_field_in_admin_orders($order){
$my_field_value = $order->get_meta('My Field');
if ( ! empty($my_field_value) ) {
echo '<p><strong>'.__('My field').':</strong> ' . $my_field_value . '</p>';
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Now If you need to extract some data from Woocommerce existing checkout fields and combine it in a custom way to save it as custom order meta data, try to be more explicit:
What fields?
How you want to combine it?
What is the custom field slug to be used to save that data combination?
I added a field at the checkout following the woocommerce documentation this way:
/*Add document ID to checkout form*/
add_filter( 'woocommerce_checkout_fields' , 'ebani_cedula_checkout_field' );
// Our hooked in function - $fields is passed via the filter!
function ebani_cedula_checkout_field( $fields ) {
$fields['billing']['cedula'] = array(
'label' => __('Cédula de ciudadanía', 'woocommerce'),
'placeholder' => _x('Cédula', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-last'),
'clear' => true,
'priority' => 15
);
return $fields;
}
Then I want to show it on the admin order edit page this way:
/**
* Display field value on the order edit page
*/
add_action( 'woocommerce_admin_order_data_after_billing_address', 'cedula_checkout_field_display_admin_order_meta', 10, 1 );
function cedula_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('Cédula').':</strong> ' . get_post_meta( $order->get_id(), '_cedula', true ) . '</p>';
}
When I go to the order edit page I get an empty value for _cedula I don't know why, I'm just following the documentation, but it is not working, how can I get the data stored in the custom checkout field?
If you want this custom billing field to be saved when order is placed, it's better to use
the action hook woocommerce_billing_fields instead of woocommerce_checkout_fields like:
add_filter( 'woocommerce_billing_fields' , 'ebani_cedula_checkout_field' );
function ebani_cedula_checkout_field( $fields ) {
$fields['billing_cedula'] = array(
'label' => __('Cédula de ciudadanía', 'woocommerce'),
'placeholder' => _x('Cédula', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array('form-row-last'),
'clear' => true,
'priority' => 15
);
return $fields;
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'cedula_checkout_field_display_admin_order_meta', 10, 1 );
function cedula_checkout_field_display_admin_order_meta($order){
if( $value = $order->get_meta('_billing_cedula') )
echo '<p><strong>'.__('Cédula').':</strong> ' . $value . '</p>';
}
Now your custom checkout billing field is saved.
In WooCommerce, at checkout, I am able to create or update all the user and billing information while placing an order. However, I want to set/update the user "display name" (alias) as well.
So based on "Capture custom checkout field value in Woocommerce" answer code, I have added the following code to my active theme's functions.php file:
// Display a custom checkout field
add_action( 'woocommerce_before_checkout_billing_form', 'my_custom_checkout_field' );
function my_custom_checkout_field( $checkout ) {
echo '<div id="my_custom_checkout_field">';
woocommerce_form_field( 'display_name', array(
'type' => 'text',
'class' => array('my-custom-field form-row-wide'),
'label' => __('Alias'),
'placeholder' => __('Nickname to show in my account and comments'),
'required' => true,
), $checkout->get_value( 'display_name' ));
echo '</div>';
}
// Save the custom checkout field in the order meta
add_action( 'woocommerce_checkout_update_user_meta', 'save_order_custom_meta_data', 10, 2 );
function save_order_custom_meta_data( ) {
if ( isset($_POST['display_name']) )
$user->update_meta_data('display_name', sanitize_text_field( $_POST['display_name'] ) );
}
But this is not working as I get "Internal Server Error" message.
Any help to solve this will be appreciated.
The problem comes from your second function… The function arguments are missing and $user variable is null and you can't use on it the WC_Data method update_meta_data().
Also the display_name is not user meta data, but simply user data. So you need to use dedicated WordPress function wp_update_user() in order to set/update the user display name.
Replace your 2nd hooked function with the following instead:
// Save/update user data from custom checkout field value
add_action( 'woocommerce_checkout_update_user_meta', 'checkout_update_user_display_name', 10, 2 );
function checkout_update_user_display_name( $customer_id, $data ) {
if ( isset($_POST['display_name']) ) {
$user_id = wp_update_user( array( 'ID' => $customer_id, 'display_name' => sanitize_text_field($_POST['display_name']) ) );
}
}
Code goes in function.php file of your active child theme (or active theme). It should works now.
In WooCommerce, I want to add some custom fields on checkout which will be displayed under the billing section on the e-mail confirmation.
My custom fields and their values, shown on the checkout form and on the order page on back end (WooCommerce -> Orders). So far everything works great.
The problem is that the e-mail that i receive does not contain the custom fields and their values.
Code shown below:
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
function custom_override_checkout_fields( $fields ) {
$fields['billing']['billing_field_testing'] = array(
'label' => __('TestingField', 'woocommerce'),
'placeholder' => _x('TestingField', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
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>'.__('TestingField').':</strong> ' . get_post_meta( $order->id, '_billing_field_testing', true ) . '</p>';
}
Please help.
Thanks in advance
Updated: To display your custom checkout field in email notifications below the billing address, use this function hooked in woocommerce_email_customer_details action hook with a priority above 20:
add_action('woocommerce_email_customer_details','add_custom_checkout_field_to_emails_notifications', 25, 4 );
function add_custom_checkout_field_to_emails_notifications( $order, $sent_to_admin, $plain_text, $email ) {
$output = '';
$billing_field_testing = get_post_meta( $order->id, '_billing_field_testing', true );
if ( !empty($billing_field_testing) )
$output .= '<div><strong>' . __( "Some text:", "woocommerce" ) . '</strong> <span class="text">' . $billing_field_testing . '</span></div>';
echo $output;
}
The Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
You will need to customize email templates under woocommerce/templates/emails/ to your-theme/woocommerce/emails/
Youc an override whatever template you want end add custom field there.
Alternatively, you can also add them using hook from following code:
add_filter( 'woocommerce_email_order_meta_fields', 'custom_woocommerce_email_order_meta_fields', 10, 3 );
function custom_woocommerce_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
$fields['meta_key'] = array(
'label' => __( 'Label' ),
'value' => get_post_meta( $order->id, 'meta_key', true ),
);
return $fields;
}