I've added custom fields to my WooCommerce registration using this process.
I've made them available on the My Account's edit page using these actions:
// added custom fields here
add_action( 'woocommerce_edit_account_form', 'my_woocommerce_edit_account_form' );
// saved user meta here
add_action( 'woocommerce_save_account_details', 'my_woocommerce_save_account_details' );
In between the two, I need to validate these fields when editing. I tried using the woocommerce_process_myaccount_field_ filter (as mentioned here) but that didn't work. The code inside it doesn't trigger when I save the changes.
Any ideas on how can I validate?
Am I using the correct filter?
If yes, why doesn't it trigger?
Thanks.
You could try to use one of this 2 hooks for validating custom fields.
add_action( 'user_profile_update_errors','wooc_validate_custom_field', 10, 1 );
// or
add_action( 'woocommerce_save_account_details_errors','wooc_validate_custom_field', 10, 1 );
// with something like:
function wooc_validate_custom_field( $args )
{
if ( isset( $_POST['custom_field'] ) ) // Your custom field
{
if(strlen($_POST['custom_field'])<4 ) // condition to be adapted
$args->add( 'error', __( 'Your error message', 'woocommerce' ),'');
}
}
Related
We have created a site using WooCommerce and WordPress with predefined products.
However, Product A must have variations, to resolve this, we added custom fields such as Colors, Dimensions, etc...
Now once the end-users are navigating to the product, we are able to fetch the custom field values. We also modified the UI so that users can pick and choose from these custom fields. (We have a preview of the modifications done via JS/CSS), so for instance, if they choose a green color we use JS to add a layer of green so that the preview is real time.
Now, we have one challenge.
-> What is the best way to go about adding this product PLUS all modifications done to the cart?
So for instance Product A was modified (on the front-end) using data pulled from the custom fields to include Color: Green and Size: 100x100 instead of defaults values. How do we store this and pass the customized product to the cart?
Appreciate the help!. Glad to add more details if something is not clear.
(There are plugins out there that can provide this functionality; Things similar to WooCommerce Product Add-On, etc... However, we have to custom develop the feature.)
It requires some steps.
1). For your product page:
First you might need to add hidden fields to the add to cart form for each custom field like (example):
add_action( 'woocommerce_before_add_to_cart_button', 'add_hidden_empty_input_fields' );
function add_hidden_empty_input_fields() {
?>
<input type="hidden" name="hidden_color" id="hidden_color" value="">
<input type="hidden" name="hidden_dimensions" id="hidden_dimensions" value="">
<?php
}
Then you will have to make some changes to your Javascript code to set the custom fields chosen values in those hidden fields.
2). Pass the custom fields selected values as custom cart item data (example):
add_filter('woocommerce_add_cart_item_data', 'add_custom_field_data', 10, 3 );
function add_custom_field_data( $cart_item_data, $product_id, $variation_id ) {
if ( isset($_POST['hidden_color']) && ! empty($_POST['hidden_color']) ) {
$cart_item_data['color'] = esc_attr($_POST['hidden_color']);
}
if ( isset($_POST['hidden_dimensions']) && ! empty($_POST['hidden_dimensions']) ) {
$cart_item_data['dimensions'] = esc_attr($_POST['hidden_dimensions']);
}
return $cart_item_data;
}
And optionally display values on cart items (example):
add_filter( 'woocommerce_get_item_data', 'display_custom_cart_item_data', 10, 2 );
function display_custom_cart_item_data( $cart_data, $cart_item ) {
if ( isset($cart_item['color']) ) {
$cart_data[] = array( "name" => __("Color"), "value" => $cart_item['color'] );
}
if ( isset($cart_item['dimensions']) ) {
$cart_data[] = array( "name" => __("Dimensions"), "value" => $cart_item['dimensions'] );
}
return $cart_data;
}
3). Save the custom cart item data as custom order item meta data (example):
add_action( 'woocommerce_checkout_create_order_line_item', 'save_custom_order_item_meta_data' , 10, 4 );
function save_custom_order_item_meta_data( $item, $cart_item_key, $values, $order ) {
if ( isset($values['color']) ) {
$item->add_meta_data( __("Color"), $values['color'] );
}
if ( isset($values['dimensions']) ) {
$item->add_meta_data( __("Dimensions"), $values['dimensions'] );
}
}
Note: The data is going to be displayed on everywhere on orders and email notifications.
Code goes in functions.php file of the active child theme (or active theme). It should work.
The variations have a post_id, you would just use the variation post_id instead of the main product one.
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.
I was trying to add new column to the orders page of the customer's recent orders table, the new column should show the details of the product like product name & description.
Tried different solution, was fortunate to add column name but not able to add the value to the column.
Here is my code:
add_filter( 'woocommerce_account_orders_columns', 'new_orders_columns' );
function new_orders_columns( $columns = array() ) {
// Hide the columns
if( isset($columns['order-total']) ) {
unset( $columns['order-status'] );
unset( $columns['order-total'] );
unset( $columns['order-actions'] );
}
// Add new columns
//this is my custom column order details
$columns['order-detail'] = __( 'Details', 'woocommerce' );
$columns['order-status'] = __( 'Status', 'woocommerce' );
$columns['order-total'] = __( 'Total', 'woocommerce' );
$columns['order-actions'] = __( ' ');
return $columns;
}
Screenshot of the result:
You are very near…
1) Insert a new column in a specific location (another way):
add_filter( 'woocommerce_account_orders_columns', 'add_custom_account_orders_column', 10, 1 );
function add_custom_account_orders_column( $columns ) {
$ordered_columns = array();
// Inserting a new column in a specific location
$ordered_columns['order-number'] = $columns['order-number'];
$ordered_columns['order-date'] = $columns['order-date'];
$ordered_columns['order-details'] = __( 'Details', 'woocommerce' ); // <== New column
$ordered_columns['order-status'] = $columns['order-status'];
$ordered_columns['order-total'] = $columns['order-total'];
$ordered_columns['order-actions'] = $columns['order-actions'];
return $ordered_columns;
}
Code goes in function.php file of your active child theme (or active theme).
tested and works.
2) Display data in this new column (editing myaccount/orders.php template):
You will need to override through your active child theme, the myaccount/orders.php WooCommerce template.
At line 56 (just after 'order-number' code) you will insert the following and you will be able to add some specific content:
<?php elseif ( 'order-details' === $column_id ) : ?>
<?php
// HERE GOES YOUR CUSTOM CODE (DISPLAYED CONTENT)
?>
You can use the available WC_Order object $order…
How to get WooCommerce order details
Accepted answer is only partially correct. Adding the column via filter is fine, but populating the column is better done via a action hook. This is clean and matches best with column being added via filter. While editing the orders.php page via child theme works, it will lead to future effort to maintain after updates to woocommerce change this page making child theme version out of date.
To add your content to the column create an action hook along side the filter in functions.php. (or better yet in a plugin!)
add_action( 'woocommerce_my_account_my_orders_column_order-detail' , 'your_function_name2',10,1 );
//'woocommerce_my_account_my_orders_column_<column_id>'
function your_function_name2( $order ) {
// do stuff, ex: get_post_meta( $post->ID, 'key', true );
}
add_filter( 'woocommerce_account_orders_columns', 'new_orders_columns',10,1 );
function new_orders_columns( $columns) {
// Add new column. Kept simple to play nice with other filters.
$columns['order-detail'] = __( 'Details', 'woocommerce' );
return $columns;
}
see this similar question, best answer by Misha
Try to use this code
<?php
// ------------------
// 1. Register new endpoint to use for My Account page
// Note: Resave Permalinks or it will give 404 error
function bbloomer_add_premium_support_endpoint() {
add_rewrite_endpoint( 'premium-support', EP_ROOT | EP_PAGES );
}
add_action( 'init', 'bbloomer_add_premium_support_endpoint' );
// ------------------
// 2. Add new query var
function bbloomer_premium_support_query_vars( $vars ) {
$vars[] = 'premium-support';
return $vars;
}
add_filter( 'query_vars', 'bbloomer_premium_support_query_vars', 0 );
// ------------------
// 3. Insert the new endpoint into the My Account menu
function bbloomer_add_premium_support_link_my_account( $items ) {
$items['premium-support'] = 'Premium Support';
return $items;
}
add_filter( 'woocommerce_account_menu_items', 'bbloomer_add_premium_support_link_my_account' );
// ------------------
// 4. Add content to the new endpoint
function bbloomer_premium_support_content() {
echo '<h3>Premium WooCommerce Support</h3><p>Welcome to the WooCommerce support area. As a premium customer, you can submit a ticket should you have any WooCommerce issues with your website, snippets or customization. <i>Please contact your theme/plugin developer for theme/plugin-related support.</i></p>';
echo do_shortcode( ' /* your shortcode here */ ' );
}
add_action( 'woocommerce_account_premium-support_endpoint', 'bbloomer_premium_support_content' );
I am working on a WordPress eCommerce website, with WooCommerce being the chosen Shopping Platform.
I have created a Custom Field, within the WooCommerce Product Dashboard by inserting the following code into the functions.php file:
function product_custom_fields_add(){
echo '<div class="product_custom_field">';
// Minimum Required Custom Letters
woocommerce_wp_text_input(
array(
'id' => '_minimum_engrave_text_option',
'name' => '_minimum_engrave_text_option',
'desc' => __('set custom minimum Lettering text field', 'woocommerce'),
'label' => __('Minimum Letters', 'woocommerce'),
'desc_tip' => 'true'
)
);
echo '</div>';
}
add_action('woocommerce_product_options_advanced', 'product_custom_fields_add');
In order to save the values, I have entered the following code into the functions.php file:
// Save Minimum Required Custom Letters
function woocommerce_product_custom_fields_save1($post_id){
if ( ! empty( $_POST['_minimum_engrave_text_option'] ) )
update_post_meta($post_id, '_minimum_engrave_text_option', esc_attr( $_POST['_minimum_engrave_text_option'] ));
}
add_action( 'woocommerce_process_product_meta', 'woocommerce_product_custom_fields_save1' );
The above code works when a value is entered into the Custom Field. My problem is that I am unable to successfully save a Blank Value. Whenever I save a Product, the Custom Field either auto populates the Field with '1' or saves a previously entered number.
I tried applying the answer, from a similar question, but could not quote get it to work.
Does anyone know where I am going wrong here?
Try to replace empty() by isset() as a condition in the if statement of your hooked function:
// Save Minimum Required Custom Letters
function woocommerce_product_custom_fields_save1($post_id){
if ( isset( $_POST['_minimum_engrave_text_option'] ) )
update_post_meta($post_id, '_minimum_engrave_text_option', esc_attr( $_POST['_minimum_engrave_text_option'] ));
}
add_action( 'woocommerce_process_product_meta', 'woocommerce_product_custom_fields_save1' );
Now this will works
I'm creating a plugin for wordpress and woocommerce. In my plugin, I've inserted an input box above the checkout form using code using 'woocommerce_before_checkout_form'. On completion of the order, I'd like to be able to add the value from that input to the order's meta data. to that end, I created this code in the functions.php file of my plugin:
add_action( 'woocommerce_checkout_update_order_meta', 'add_input_meta', 1, 2 );
function add_input_meta( $order_id, $posted ) {
$inputsData = $_POST['InputBox'];
update_post_meta( $order_id, 'my_key', $inputsData);
}
The problem is, it returns NULL every time. I created the code below to see what the value of $_POST and it came up with 'array(0) { }'
function debugthing( $content ) {
$content .=var_dump($_POST);
return $content;
die();
}
add_filter( 'the_content', 'debugthing' );
I've exhausted every idea I could ahve about what is causing this. can anyone help?
$_POST, even php://input return an empty array or absolutely nothing.
woocommerce_before_checkout_form is not the right hook to add input fields. For this hook is outside the form. This explains why you are getting null on $_POST
use any of the hook inside the <form in form-checkout.php#L35
call woocommerce_form_field to add fields...
next is you need to hook inside process_checkout() function.
a. woocommerce_after_checkout_validation - for input validations...
b. woocommerce_checkout_order_processed - order created, do your meta data addition...
// add form fields
add_action( 'woocommerce_checkout_before_customer_details', 'woocommerce_checkout_before_customer_details' );
function woocommerce_checkout_before_customer_details() {
$args = array(
'type' => 'text',
'label' => 'My Custom field',
'description' => 'This is custom field',
'placeholder' => '',
'required' => true,
);
woocommerce_form_field( 'InputBox' , $args ); // you can call woocommerce_form_field as many as you want...
}
// validate your form field(s)
add_action( 'woocommerce_after_checkout_validation', 'woocommerce_after_checkout_validation' );
function woocommerce_after_checkout_validation() {
// $_POST['InputBox'] will be visible here...
// do your validations here... forget this hook if you don't need to validate...
// wc_add_notice( __( 'Invalid message!', 'woocommerce' ), 'error' );
// call wc_add_notice if you want to invalidate the form.
}
add_action( 'woocommerce_checkout_order_processed', 'woocommerce_checkout_order_processed' );
function woocommerce_checkout_order_processed( $order_id ) {
// we now have $order_id, you can now add your meta data....
}
change your hook priority like this.
add_action( 'woocommerce_checkout_update_order_meta', 'add_input_meta', 99, 2 );