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.
Related
In WooCommerce checkout page, I have added a custom field using the code below:
add_action( 'woocommerce_before_order_notes', 'bbloomer_add_custom_checkout_field' );
function bbloomer_add_custom_checkout_field( $checkout ) {
$current_user = wp_get_current_user();
$saved_gst_no = $current_user->gst_no;
woocommerce_form_field( 'gst_no', array(
'type' => 'text',
'class' => array( 'form-row-wide' ),
'label' => 'GST Number',
'placeholder' => 'GST Number',
'required' => true
//'default' => $saved_gst_no,
), $checkout->get_value( 'gst_no' ) );
error_log( $checkout->get_value( 'gst_no' ) );
}
On entering any value in GST Number field (custom checkout field), then going to payment screen by clicking "Place order" button and returning to checkout page without completing the transaction, all default woocommerce fields like billing phone, email etc are auto filled from the session.
However, the custom field added via above code is always blank. I tried logging the value of $checkout->get_value( 'gst_no' ) and it is always null.
How to make the $checkout object store custom field values?
Update 2
Because you need to save 'gst_no' custom field value as user data too. The following will save that custom field as user meta data:
add_action( 'woocommerce_checkout_update_customer', 'action_checkout_update_customer', 10, 2 );
function action_checkout_update_customer( $customer, $data ) {
if( isset($_POST['gst_no']) ) {
$customer->update_meta_data( 'gst_no', sanitize_text_field($_POST['gst_no']) );
}
}
Code goes in functions.php file of the active child theme (or active theme). It should work.
Note: For info, the WC_Checkout method get_value() use the user meta data.
I have added a custom field using the below code:
add_action( 'woocommerce_before_order_notes', 'bbloomer_add_custom_checkout_field' );
function bbloomer_add_custom_checkout_field( $checkout ) {
$current_user = wp_get_current_user();
$saved_gst_no = $current_user->gst_no;
woocommerce_form_field( 'gst_no', array(
'type' => 'text',
'class' => array( 'form-row-wide' ),
'label' => 'GST Number',
'placeholder' => 'GST Number',
'required' => true
//'default' => $saved_gst_no,
), $checkout->get_value( 'gst_no' ) );
}
On entering any value in GST Number field (custom checkout field), then going to payment screen by clicking "Place order" button and returning to checkout page without completing the transaction, all default woocommerce fields like billing phone, email etc are auto filled from the session.
However, the custom field added via above code is always blank. How to get the previously entered value auto-filled in the custom field for guest users, similar to the way default woocommerce fields are auto-filled?
Updated (replaced wrong WC_Session method set() with get() on the first function)
This will work for guest users too. Replace your code with:
// Display checkout custom field
add_action( 'woocommerce_before_order_notes', 'add_custom_checkout_field' );
function add_custom_checkout_field( $checkout ) {
$key_field = 'gst_no';
woocommerce_form_field( $key_field, array(
'type' => 'text',
'class' => array( 'form-row-wide' ),
'label' => __('GST Number'),
'placeholder' => __('GST Number'),
'required' => true
//'default' => $saved_gst_no,
), $checkout->get_value($key_field) ? $checkout->get_value($key_field) : WC()->session->get($key_field) );
}
// Save checkout custom field value in a WC_Session variable
add_action( 'woocommerce_checkout_create_order', 'action_checkout_create_order', 10, 2 );
function action_checkout_create_order( $order, $data ) {
$key_field = 'gst_no';
if( isset($_POST[$key_field]) ) {
WC()->session->set($key_field, sanitize_text_field($_POST[$key_field]));
}
}
// Save checkout custom field value as user meta data
add_action( 'woocommerce_checkout_update_customer', 'action_checkout_update_customer', 10, 2 );
function action_checkout_update_customer( $customer, $data ) {
$key_field = $key_field;
if( isset($_POST['gst_no']) ) {
$customer->update_meta_data($key_field, sanitize_text_field($_POST[$key_field]));
}
}
Note: Uses a WC_Session variable to store the submitted value for guests, allowing to display it on checkout when returning without completing the transaction.
In my experience, WooCommerce was saving the form data in session variables via AJAX when fields were updated via the update_order_review path. In order to hook into this and stored my custom vars, I used the following:
add_action('woocommerce_checkout_update_order_review', 'custom_woocommerce_checkout_update_order_review');
function custom_woocommerce_checkout_update_order_review($post_data){
// Convert $post_data string to array and clean it
$post_arr = array();
parse_str($post_data, $post_arr);
wc_clean($post_arr);
if(isset($post_arr['gst_no'])) {
WC()->session->set('gst_no', $post_arr['gst_no']);
}
}
Also a deeper way to add the custom checkout fields so that it's available in the $data passed to woocommerce_checkout_update_order_meta:
add_filter('woocommerce_checkout_fields', 'custom_checkout_fields');
function custom_checkout_fields($fields){
$fields['gst_no'] = array(
'type' => 'text',
'default' => WC()->session->get('gst_no')
);
return $fields;
}
How do I set the value of a custom field on an order, upon checkout submit, to a selected value in an HTML component?
I've implemented a custom HTML component, inside the checkout form, whose selected value I want to insert in a custom field on my orders. But I can't seem to figure out how to hook these things up.
I've arrived at somthing like:
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
function custom_override_checkout_fields( $fields ) {
$fields['order']['special_delivery'] = 'The value from HTML';
return $fields;
}
But I'm not even sure that's the right way to go.
Any ideas?
Using woocommerce_after_checkout_billing_form allows you to add custom fields to your checkout form. You also need to save the field in the order meta using woocommerce_checkout_update_order_meta.
In the following code there is a custom text field used for saving VAT ID. Feel free to get rid of the "mrank" prefixes. Also rename the field as you need it.
It will show you how to add a field and to save in order meta.
/**
* VAT Number in WooCommerce Checkout
*/
function mrank_vat_field( $checkout ) {
echo '<div id="mrank_vat_field">';
woocommerce_form_field( 'vat_number', array(
'type' => 'text',
'class' => array( 'vat-number-field form-row-wide') ,
'label' => __( 'VAT-ID' ),
'placeholder' => __( 'Enter number' ),
'description' => __( 'Please enter your VAT-ID' ),
'required' => true,
), $checkout->get_value( 'vat_number' ));
echo '</div>';
}
add_action( 'woocommerce_after_checkout_billing_form', 'mrank_vat_field' );
/**
* Save VAT Number in the order meta
*/
function mrank_checkout_vat_number_update_order_meta( $order_id ) {
if ( ! empty( $_POST['vat_number'] ) ) {
update_post_meta( $order_id, '_vat_number', sanitize_text_field( $_POST['vat_number'] ) );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'mrank_checkout_vat_number_update_order_meta' );
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.
So I've got the following function to add a barcode field in the Product Inventory tab. However this field is being added after all the other content, and I would like to have this before the SKU code.
function add_barcode(){
global $woocommerce,$post;
woocommerce_wp_text_input(
array(
'id' => '_barcode',
'label' => __('Barcode','woocommerce'),
'placeholder' => 'Scan Barcode',
'desc_tip' => 'true',
'description' => __('Scan barcode.','woocommerce')
));
}
add_action('woocommerce_product_options_inventory_product_data','add_barcode');
Is there anyway to place the function/field before the SKU aka before the actual hook, like something in terms of woocommerce_before_product_options_inventory_product_data?
Thanks for any suggestions in advance.
IS NOT POSSIBLE TO PLACE ANY CUSTOM FIELD BEFORE THE SKU
You can take a look to html-product-data-inventory.php source code file which displays product inventory fields.
But you can display your 'Barcode' custom field just after the SKU field (for example)
For that you have to hook your custom function in woocommerce_product_options_sku action hook instead. There is also some missing things in your code to display a saved value.
And finally you need another function to save that value when product is saved or updated.
Here is that complete code:
add_action('woocommerce_product_options_sku','add_barcode_custom_field' );
function add_barcode_custom_field(){
woocommerce_wp_text_input( array(
'id' => '_barcode',
'label' => __('Barcode','woocommerce'),
'placeholder' => 'Scan Barcode',
'desc_tip' => 'true',
'description' => __('Scan barcode.','woocommerce')
) );
}
add_action( 'woocommerce_process_product_meta', 'save_barcode_custom_field', 10, 1 );
function save_barcode_custom_field( $post_id ){
if( isset($_POST['_barcode']) )
update_post_meta( $post_id, '_barcode', esc_attr( $_POST['_barcode'] ) );
}
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 2.6+ and 3.0+