I have a custom field for customer-id for client's ordering system, the field works and everything but for some odd reason, it won't send in an email or show in the order information in the admin areas. I have all of the proper code from WooDocs but it doesn't seem to work, my code is below. The link for the docs below.
Customizing checkout fields using actions and filters
/**
* Add the field to the checkout
**/
add_action('woocommerce_before_order_notes', 'my_custom_checkout_field',30);
function my_custom_checkout_field( $checkout ) {
woocommerce_form_field( 'customer_number', array(
'type' => 'text',
'class' => array('form-row-wide'),
'label' => __('Customer Number <small>(Enter a customer number or leave empty)</small>'),
'placeholder' => __('Enter a number'),
'required' => false,
), $checkout->get_value( 'customer_number' ));
}
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['customer_number'] ) ) {
update_post_meta( $order_id, 'Customer Number', sanitize_text_field( $_POST['customer_number'] ) );
}
}
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>'.__('Customer Number').':</strong> ' . get_post_meta( $order->id, 'Customer Number', true ) . '</p>';
}
add_filter('woocommerce_email_order_meta_keys', 'my_custom_order_meta_keys');
function my_custom_order_meta_keys( $keys ) {
$keys[] = 'Customer Number'; // This will look for a custom field called 'Customer Number' and add it to emails
return $keys;
}
Thanks in advance!
Related
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 have successfully added the phone number field in Ship to different address and the phone number is showing in back-end as well. However I am not receiving the phone number in email.
Kindly Help
This code helps me to add field:
add_filter( 'woocommerce_checkout_fields', 'bbloomer_shipping_phone_checkout' );
function bbloomer_shipping_phone_checkout( $fields ) {
$fields['shipping']['shipping_phone'] = array(
'label' => 'Phone',
'required' => true,
'class' => array( 'form-row-wide' ),
);
return $fields;
}
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'bbloomer_shipping_phone_checkout_display' );
function bbloomer_shipping_phone_checkout_display( $order ){
echo '<p><b>Shipping Phone:</b> ' . get_post_meta( $order->get_id(), '_shipping_phone', true ) . '</p>';
}
I have tried adding additional code in the above code (shown below) to show the phone number in email. Still doesn't work!
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' => __( 'Shipping Phone' ),
'value' => get_post_meta( $order->id, '_shipping_phone', true ),
);
return $fields;
}
You're missing the correct meta_key, I have also slightly modified your existing code.
Note: by adjusting the priority argument, you can set your field in the correct location.
So you get:
// Shipping field on my account edit-addresses and checkout
function filter_woocommerce_shipping_fields( $fields ) {
$fields['shipping_phone'] = array(
'label' => __( 'Shipping Phone', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-wide' ),
'priority' => 55
);
return $fields;
}
add_filter( 'woocommerce_shipping_fields' , 'filter_woocommerce_shipping_fields', 10, 1 );
// Display on the order edit page (backend)
function action_woocommerce_admin_order_data_after_shipping_address( $order ) {
if ( $value = $order->get_meta( '_shipping_phone' ) ) {
echo '<p><strong>' . __( 'Shipping Phone', 'woocommerce' ) . ':</strong> ' . $value . '</p>';
}
}
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'action_woocommerce_admin_order_data_after_shipping_address', 10, 1 );
// Display on email notifications
function filter_woocommerce_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
// Get meta
$shipping_phone = $order->get_meta( '_shipping_phone' );
// NOT empty
if ( ! empty( $shipping_phone ) ) {
$fields['_shipping_phone'] = array(
'label' => __( 'Shipping Phone', 'woocommerce' ),
'value' => $shipping_phone,
);
}
return $fields;
}
add_filter( 'woocommerce_email_order_meta_fields', 'filter_woocommerce_email_order_meta_fields', 10, 3 );
I've added a custom field to the checkout page on my Woocommerce store. The field is 'Restaurant Location'. Upon a customer placing an order, my goal is to use the 'Restaurant Location' field to determine which email to send the order confirmation to.
Here's how I defined the custom field.
/////// Hook custom field in ///////
add_filter( 'woocommerce_checkout_fields', 'custom_checkout_fields' );
function custom_checkout_fields( $fields ) {
$fields['order']['restaurant_location'] = array(
'label' => __('Food options', 'woocommerce'),
'placeholder' => _x('', 'placeholder', 'woocommerce'),
'required' => true,
'clear' => false,
'type' => 'select',
'options' => array(
'no' => __('New Orleans', 'woocommerce' ),
'br' => __('Baton Rouge', 'woocommerce' )
)
);
return $fields;
}
Here's my attempt at the email filter.
add_filter( 'woocommerce_email_recipient_new_order', 'gon_conditional_email_recipient', 10, 2 );
function gon_conditional_email_recipient( $recipient, $order ) {
$gon_order_data = $order->get_data();
$gon_restaurant_location = $gon_order_data['order']['restaurant_location'];
if ( $gon_restaurant_location == 'New Orleans' ) {
$recipient = 'test1#gmail.com';
return $recipient;
}
else if ( $gon_restaurant_location == 'Baton Rouge' ) {
$recipient = 'test2#gmail.com';
return $recipient;
}
return $recipient;
}
The email filter is working, i.e. I can get an email to go to either address, but I can't seem to pull in the '$gon_restaurant_location' variable properly. Any ideas?
Thanks,
pS
Your custom field value is not saved in database, so that's why is not working. Try this complete solution instead:
// Add the custom checkout field
add_filter( 'woocommerce_after_order_notes', 'restaurant_location_checkout_field' );
function restaurant_location_checkout_field( $checkout ) {
woocommerce_form_field( 'restaurant_location', array(
'type' => 'select',
'class' => array('my-field-class form-row-wide'),
'label' => __('Food options', 'woocommerce'),
'required' => true,
'options' => array(
'' => __('Please select an option', 'woocommerce' ),
'New Orleans' => __('New Orleans', 'woocommerce' ),
'Baton Rouge' => __('Baton Rouge', 'woocommerce' )
)
), $checkout->get_value( 'restaurant_location' ));
}
// Process the checkout (checking)
add_action('woocommerce_checkout_process', 'restaurant_location_field_process');
function restaurant_location_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['restaurant_location'] )
wc_add_notice( __( 'Please select a food option .' ), 'error' );
}
// Update the order meta with field value
add_action( 'woocommerce_checkout_update_order_meta', 'restaurant_location_field_update_order_meta' );
function restaurant_location_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['restaurant_location'] ) ) {
update_post_meta( $order_id, '_restaurant_location', sanitize_text_field( $_POST['restaurant_location'] ) );
}
}
// Display field value on the order edit page
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>'.__('Food options', 'woocommerce').':</strong> ' . get_post_meta( $order->get_id(), '_restaurant_location', true ) . '</p>';
}
// Conditional Email recipient filter based on restaurant location
add_filter( 'woocommerce_email_recipient_new_order', 'conditional_email_recipient', 10, 2 );
function conditional_email_recipient( $recipient, $order ) {
if( is_admin() ) return $recipient;
$location = get_post_meta( $order->get_id(), '_restaurant_location', true );
$recipient = $location == 'New Orleans' ? ',test1#example.com' : ',test1#example.com';
return $recipient;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on Woocommerce 3+ and works
Based on official developer documentation: Adding a custom special field
I'm adding WooCommerce custom checkout fields in a Storefront child theme functions.php file.
They have a "required" attribute.
The aim is to have these fields appear at the top of the page, before the billing fields.
when clicking the submit button to proceed to payment, I'm getting the required custom field validation error ('please fill in your name') and can't continue with payment, even though filling the field with valid data.
Any clue how to fix this or where to start debugging ?
here is the code in functions.php:
add_action( 'woocommerce_before_checkout_form', 'my_custom_checkout_fields' );
function my_custom_checkout_fields( $checkout ) {
echo '<div id="my_custom_checkout_field" class="col4-set"><h2>' . __('name') . '</h2>';
woocommerce_form_field( 'developer_name', array(
'type' => 'text',
'class' => array('developer_name-class form-row form-row-first'),
'label' => __('name'),
'placeholder' => __('fill in your name'),
'required' => true,
), $checkout->get_value( 'developer_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['developer_name'] )
wc_add_notice( __( 'please fill in your name' ), 'error' );
}
I tried the following but none of them helped:
1. changing:
if ( ! $_POST['developer_name'] )
to
if ( empty( $_POST['developer_name']) )
2. changing the trigger from:
add_action( 'woocommerce_before_checkout_form', 'my_custom_checkout_fields' );
to
add_action( 'woocommerce_after_checkout_form', 'my_custom_checkout_fields' );
3. updating to latest Woocomerce 3.0.5 version
I'm running Wordpress 4.7.4
additional related active plugins:
Uni CPO - WooCommerce Options and Price Calculation Formulas
As you can read in woocommerce_before_checkout_form hook, it's before checkout form (so outside the checkout form). For this reason this custom field can't work in this hook.
You can use instead woocommerce_checkout_update_order_meta action hook, making some little changes in your code as there is no $checkout argument available in it.
This will display the field "at the top of the page, before the billing fields"…
So your complete code should be now:
/**
* Add the field to the checkout
*/
add_action( 'woocommerce_checkout_before_customer_details', 'my_custom_checkout_fields' );
function my_custom_checkout_fields() {
echo '<div id="my_custom_checkout_field" class="col4-set"><h2>' . __('name') . '</h2>';
woocommerce_form_field( 'developer_name', array(
'type' => 'text',
'class' => array('developer_name-class form-row form-row-first'),
'label' => __('name'),
'placeholder' => __('fill in your name'),
'required' => true,
), WC()->checkout->get_value( 'developer_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['developer_name'] )
wc_add_notice( __( 'Please fill in your name.' ), 'error' );
}
// Update the order meta with field value
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta', 10, 1 );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['developer_name'] ) ) {
update_post_meta( $order_id, 'Developer name', sanitize_text_field( $_POST['developer_name'] ) );
}
}
// Display the custom-field in orders view
add_action( 'woocommerce_order_details_after_customer_details', 'display_my_custom_field_in_orde_details', 10, 1 );
function display_my_custom_field_in_orde_details( $order ) {
$developer_name = get_post_meta( $order->get_id(), 'Developer name', true );
if ( ! empty( $developer_name ) ):
?>
<table class="woocommerce-table woocommerce-table--customer-details shop_table customer_details">
<tbody><tr>
<th>Developer name:</th>
<td><?php echo $developer_name; ?></td>
</tr></tbody>
</table>
<?php
endif;
}
This 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 for WooCommerce version 3.0+
You try this code. Tested Ok
add_action( 'woocommerce_billing_fields', 'my_custom_checkout_fields' );
function my_custom_checkout_fields( $fields ) {
$fields['billing_developer_name'] = array(
'label' => __('Developer name', 'woocommerce'),
'placeholder' => _x('Developer name', 'placeholder', 'woocommerce'),
'required' => TRUE,
'clear' => false,
'type' => 'text',
'class' => array('my-css')
);
return $fields;
}
You can arrange it with this snippet
add_filter("woocommerce_checkout_fields", "order_fields");
function order_fields($fields) {
$order = array(
"billing_developer_name",
"billing_first_name",
"billing_last_name",
"billing_company",
"billing_address_1",
"billing_address_2",
"billing_postcode",
"billing_country",
"billing_email",
"billing_phone"
);
foreach($order as $field)
{
$ordered_fields[$field] = $fields["billing"][$field];
}
$fields["billing"] = $ordered_fields;
return $fields;
}
See screenshot
**/* If You Have Created Your Custom Field at the checkout page */**
add_action( 'woocommerce_after_checkout_validation', 'shipping_time_optionss', 9999, 2);
function shipping_time_optionss( $fields, $errors ){
// if any validation errors
if ( empty( $_POST['woo_shipping_time'] ) ) {
$errors->add( 'woocommerce_password_error', __( 'Please Select Shipping Time Option.' ) );
} `enter code here`
}
How to add Custom Product Fields in WooCommerce
I followed the guide above and add the code below to my functions.php. That worked fine. My problem is how to I modify this code to save the coupon code $_POST['coupon_code'] entered (during checkout) and save that to the custom field? I am stuck at that point, since my overall goal is to test the coupon code and fill the custom field with the salesperson that promoted that coupon code to the customers.
Thank you for any help!
/**
* 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>';
}
/**
* 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'] ) );
}
}
/**
* Display field value on the order edit page
*/
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>'.__('My Field').':</strong> ' . get_post_meta( $order->id, 'My Field', true ) . '</p>';
}
If you are still looking for answers, I managed to spice up your code with some help from my own question as I was in a similair situation.
Fill out custom field with used coupon code WooCommerce
your code and my edits were changed to where it actually saves the coupons to a custom value. On of the problems with your code was how you tried to reach the custom field with 'My field'. I have replaced these with the actual name of the field.
/**
* 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>';
}
/**
* 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, $posted ) {
if ( isset($_POST['my_field_name']) && empty( $_POST['my_field_name'])) {
$order = new WC_Order( $order_id );
foreach( $order->get_used_coupons() as $coupon) {
$coupons .= $coupon.', ';
}
update_post_meta( $order_id, 'my_field_name', $coupons);
}
}
/**
* Display field value on the order edit page
*/
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>'.__('My Field').':</strong> ' . get_post_meta( $order->id, 'my_field_name', true ) . '</p>';
}
You might want to clean up a bit before using this code. ;)
Source: Fill out custom field with used coupon code WooCommerce