Change default checkout field value on order creation in Woocommerce 3 - php

In Woocommerce, I am trying to display Email & Phone input fields as a custom field above billing address section.
This is what I did, but failed:
I created some custom fields and displayed them above the billing section. Also, I set the default Email and Phone fields as optional, and removed them. Woo saves order email as a meta into wp_postmenta database table. When I save custom fields, I try to overwrite these meta values with $order->update_meta_data() function, but instead of overwriting it creates a new meta with same meta_key.
function save_extra_checkout_fields( $order, $data ){
if( isset( $data['some_field'] ) ) {
$order->delete_meta_data('_billing_email');
$order->update_meta_data( '_billing_email', sanitize_email( $data['some_field'] ) );
}
}
add_action( 'woocommerce_checkout_create_order', 'save_extra_checkout_fields', 10, 2 );
As you can see even if I try to delete default meta first a duplication occurs.
It is possible to achieve this customization with hooks and filters without hacking the fields in the database, or do you have any idea how to overwrite meta value?
Any help please is welcome.

As billing email is a default field and not custom checkout field, you need to change your code a bit using set_billing_email() WC_Order method instead:
add_action( 'woocommerce_checkout_create_order', 'change_billing_email_checkout_field_value', 10, 2 );
function change_billing_email_checkout_field_value( $order, $data ){
if( isset( $data['some_field'] ) && ! empty( $data['some_field'] ) )
$order->set_billing_email( sanitize_email( $data['some_field'] ) );
}
Code goes in function.php file of your active child theme (or active theme). It should works.

Related

Add a custom field to an order in WooCommerce 3+

In WooCommerce, I would like to add a new custom field to order details. I now that I can use use the code below to create a new custom field 'referenceNumber' and adds in it "ordercreated" value:
update_post_meta($order_id, 'referenceNumber', 'ordercreated']);
What I would like is to make that through checkout once an order is placed.
But it doesn't work it doesn't add a new custom field to order details page and don't add the value 'ordercreated', as you can see in this screenshot:
So the question is how to add a custom field when an order is placed in WooCommerce?
To add a custom field to an order you can use:
WordPress update_post_meta() function (from an order id):
$order_id = $order->get_id(); // If needed
update_post_meta($order_id, 'referenceNumber', 'ordercreated'); // add and save the custom field
WooCommerce WC_Data update_meta_data() method (from the order object or the order id):
$order = wc_get_order( $order_id ); // If needed: Get the WC_Order object from the order Id
update_meta_data('referenceNumber', 'ordercreated'); // Add the custom field
$order->save(); // Save the data
Where referenceNumber is the meta key and ordercreated is the meta value. Both works.
Now to add a custom field to an order when customer place an order, you can use:
woocommerce_checkout_create_order action hook (before order data is saved - used to adjust order data before it's saved):
add_action( 'woocommerce_checkout_create_order', 'add_custom_field_on_placed_order', 10, 2 );
function add_custom_field_on_placed_order( $order, $data ){
$order->update_meta_data( 'referenceNumber', 'ordercreated' );
}
woocommerce_checkout_update_order_meta action hook (order already exist - used to add custom meta data):
add_action( 'woocommerce_checkout_create_order', 'add_custom_field_on_placed_order', 10, 2 );
function add_custom_field_on_placed_order( $order_id, $data ){
$order->update_meta_data( 'referenceNumber', 'ordercreated' );
}
woocommerce_checkout_order_created action hook (order already exist - to trigger an action or also to add custom meta data):
add_action( 'woocommerce_checkout_order_created', 'add_custom_field_on_placed_order', 10, 2 );
function add_custom_field_on_placed_order( $order_id, $data ){
$order->update_meta_data( 'referenceNumber', 'ordercreated' ); // Add the custom field
$order->save(); // Save data (as order exist yet)
}
Or:
add_action( 'woocommerce_checkout_order_created', 'add_custom_field_on_placed_order' );
function add_custom_field_on_placed_order( $order ){
update_post_meta($order->get_id(), 'referenceNumber', 'ordercreated');
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Hi i had a similar requirement few days ago, as i needed to add new field at checkout. Following article helped me. You can check it too. Here is the link. Basically you will have a write a function which will use woo commerce hook "woocommerce_default_address_fields"
https://wisdmlabs.com/blog/add-custom-fields-woocommerce-checkout-page/

Get custom field value in woocommerce_checkout_create_order hook

What am I doing wrong with this code? I am not able to retrieve the post_meta value. I know it is saved correctly because the values are displayed in the order edit page. I am just not able to retrieve in this function:
add_action( 'woocommerce_checkout_create_order', 'rev_change_total_on_checkout', 20, 1 );
function rev_change_total_on_checkout( $order ) {
$new_total_price = get_post_meta( $order->id, '_rev_fee_estimate', true);
$order->set_total($new_total_price );
}
Basically, I am trying to change the total order value after the checkout is submitted based on the values programmatically generated in a custom field value I added to the checkout form. If I hardcode the value of $new_total_price, I am able to achieve this, so I know this function works. I only need to retrieve the saved value of the custom field to finish this.
In think that _rev_fee_estimate is not saved to database yet in this hook as it's a custom field. So you can get anything related.
Instead you need to get the posted value. I will use the key _rev_fee_estimate but it can be something else (you can check for it, inspecting the generated html code for this custom field on checkout page. The necessary key is the attribute "name" value in this field)…
The code:
// Save an additional coverstart value in in the order post meta dat
add_action( 'woocommerce_checkout_create_order', 'initial_coverstart_custom_field_save', 20, 1 );
function initial_coverstart_custom_field_save( $order ) {
if( ! isset($_POST['_rev_fee_estimate']) ) return;
if( ! empty($_POST['_rev_fee_estimate']) )
{
$new_total_price = (float) sanitize_text_field( $_POST['_rev_fee_estimate'] )
$order->set_total( $new_total_price );
}
}
Code goes in function.php file of your active child theme (or active theme). It should work once you will have checked that you have the correct key for this custom field.

Add Custom attributes from a variable product to cart in WooCommerce

I am trying to redirect my custom shop page to cart page after user select custom attributes (liability and hours) and then clicks the purchase button.
I have written custom JS code which retrieves the variation_id and attributes value and append it to the URL so that it automatically gets added to cart and get's redirected to cart page.
href="yourdomain.com/?add-to-cart=47&variation_id=88&quantity=3&attribute_pa_colour=blue&attribute_pa_size=m"
This is the URL format which I have found in a blog: (https://businessbloomer.com/woocommerce-custom-add-cart-urls-ultimate-guide/) and I made my link in this format.
My link is:
localhost/wordpress/cart/?add-to-cart=1185&variation_id=1641&quantity=1&attribute_pa_liability=2_million&attribute_pa_hours=500_hours
Where liability and hours is my custom attribute which has values as 1 million, 2 million and 500 hours, 750 hours respectively.
But when it get's redirected to cart page woocommerce give me an error and shows it's alert box which shows the error message as "liability and hours are required fields".
I think woocommerce is unable to get the attribute values through my URL.
Can anyone explain why is this happening and what is the error if there is any?
Updated
This "Business Bloomer" guide is a little outdated… You need 2 things:
1). The correct URL
You don't need to addto cart the product and the variation Id with all related attributes. You just need to add to cart the variation ID + your custom attributes like this: localhost/wordpress/cart/?add-to-cart=1641&quantity=1&pa_liability=2_million&pa_hours=500_hours
2). Registering (and display) your custom attributes:
// Store the custom data to cart object
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_product_data', 10, 2 );
function save_custom_product_data( $cart_item_data, $product_id ) {
$bool = false;
$data = array();
if( isset( $_REQUEST['pa_liability'] ) ) {
$cart_item_data['custom_data']['pa_liability'] = $_REQUEST['pa_liability'];
$data['pa_liability'] = $_REQUEST['pa_liability'];
$bool = true;
}
if( isset( $_REQUEST['pa_hours'] ) ) {
$cart_item_data['custom_data']['pa_hours'] = $_REQUEST['pa_hours'];
$data['pa_hours'] = $_REQUEST['pa_hours'];
$bool = true;
}
if( $bool ) {
// below statement make sure every add to cart action as unique line item
$cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'custom_variations', $data );
}
return $cart_item_data;
}
// Displaying the custom attributes in cart and checkout items
add_filter( 'woocommerce_get_item_data', 'customizing_cart_item_data', 10, 2 );
function customizing_cart_item_data( $cart_data, $cart_item ) {
$custom_items = array();
if( ! empty( $cart_data ) ) $custom_items = $cart_data;
// Get the data (custom attributes) and set them
if( ! empty( $cart_item['custom_data']['pa_liability'] ) )
$custom_items[] = array(
'name' => 'pa_liability',
'value' => $cart_item['custom_data']['pa_liability'],
);
if( ! empty( $cart_item['custom_data']['pa_hours'] ) )
$custom_items[] = array(
'name' => 'pa_hours',
'value' => $cart_item['custom_data']['pa_hours'],
);
return $custom_items;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works
You will need to add this data to the order items too
First uncheck the ajax add to cart option from admin panel
Then you need to make variation with your attributes then find out product id, quantity, attribute slug and attribute name(used to show in cart) and variation id and then make your cart url like given below.
The add to cart link with attribute is : https://www.your-domain.com/?add-to-cart=(product id)&quantity=(numeric quantity)&attribute_pa_(attribute slug)=(attribute name)&variation_id=(variation id)
For more details you can visit http://www.codemystery.com/wordpress-woocommerce-add-cart-link-variations/
The other answers are correct in regards to the add to cart url format (should be: /add-to-cart=product_id&my_custom_attr=whatever&my_custom_attr2=somthing)
Then there is a very good plugin to handle this type of functionality for storing the custom product attributes called WC Fields Factory.
And the writer of the plugin also has a great article on how to do this w/o need of a plugin. As well as an answer on a similar question here.

Add a custom field in Woocommerce admin order list "Order" existing column

I am trying to add mycustomfield21 (added to checkout with woo checkout manager) on bulk order details on woocommerce dashboard. Here is a screenshot to show what I need:
EDITED QUESTION
I already instert 2 fields, wich are first name (myfield21) and surname (myfield22), How can I do to display a white space between them? because it shows like "first namesurname"
Update - Nov. 2018 - Added compatibility with Woocommerce version 3.3+
This is possible hooking a custom function in manage_shop_order_posts_custom_column action hook. Below I am adding the billing phone to the existing Order ("Pedido") column data:
add_action( 'manage_shop_order_posts_custom_column' , 'custom_orders_list_column_content', 10, 2 );
function custom_orders_list_column_content( $column, $post_id ) {
if ( $column == 'order_title' || $column == 'order_number' )
{
// The billing phone for example (to be repaced by your custom field meta_key)
$custom_field_value = get_post_meta( $post_id, '_billing_phone', true );
if( ! empty( $custom_field_value ) )
echo $custom_field_value;
}
}
*Code goes in function.php file of your active child theme (or active theme) . Tested and works

Avoid WooCommerce Checkout Billing form to overwrite default Wordpress user data

in the database we have metauser table that contain:
The first_name and last_name fields
Those are the default Wordpress first and last name.
And also we have:
The billing_first_name and billing_last_name.
now when user fill out the billing form and proceed the checkout process,
Woocommerce update both fields with the new values from billing name fields
(the default ones).
I have tried many things used actions like:
woocommerce_before_checkout_billing_form
or
woocommerce_after_checkout_billing_form
Also tried to update meta with:
update_user_meta()
But it's not working.
I want it to not overwrite the default first_name and last_name,
but keep the new values only in billing_first_name and billing_last_name
I think the default process is like that
https://gist.github.com/claudiosanches/ae9a8b496c431bec661b69ef73f1a087
Any help on this please?
The way is to use a custom funtion hooked in woocommerce_checkout_update_customer action hook:
add_action('woocommerce_checkout_update_customer','custom_checkout_update_customer', 10, 2 );
function custom_checkout_update_customer( $customer, $data ){
if ( ! is_user_logged_in() || is_admin() ) return;
// Get the user ID
$user_id = $customer->get_id();
// Get the default wordpress first name and last name (if they exist)
$user_first_name = get_user_meta( $user_id, 'first_name', true );
$user_last_name = get_user_meta( $user_id, 'last_name', true );
if( empty( $user_first_name ) || empty( $user_last_name ) ) return;
// We set the values by defaul worpress ones, before it's saved to DB
$customer->set_first_name( $user_first_name );
$customer->set_last_name( $user_last_name );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works in WooCommerce 3+

Categories