WooCommerce : add custom fields to product variations - php

I need help adding custom fields to my Product Variations and Simple Product pages. I tried using RemiCorson's info (http://www.remicorson.com/woocommerce-custom-fields-for-variations/), but I keep getting an error. I tried to duplicate what I saw in this user's posts for ISBN but it's not working for me.
The problem with the code below is that it doesn't show up on the live site. All help is greatly appreciated, I've spent most of today trying to figure out what I'm doing wrong.
Adding 6 custom text fields and 1 check box to both Simple Product and Variable Product pages in Woocommerce. These are not fields to be supplied (i.e. filled out) by the shopper, but rather custom information I want displayed on my product pages (and NOT within a tab).
// Display Fields
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );
// Save Fields
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
// Custom fields will be created here...
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_ISBN_field',
'label' => __( 'ISBN', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'ISBN.', 'woocommerce' )
)
);
function woo_add_custom_general_fields_save( $post_id ){
// Customer text ISBN Field
$woocommerce_text_field = $_POST['_ISBN_field'];
if( !empty( $woocommerce_text_field ) )
update_post_meta( $post_id, '_ISBN_field', esc_attr( $woocommerce_text_field ) );
else
update_post_meta( $post_id, '_ISBN_field', '' );
}
// Display Custom Field Value
echo get_post_meta( $post->ID, '_ISBN_field', true );
}
/* WooCommerce */
/* ----------------------------------------------------------------------------------- */
/* Start WooThemes Functions - Please refrain from editing this section */
/* ----------------------------------------------------------------------------------- */

I have never needed to bother with woocommerce_product_after_variable_attributes_js, you just need to add the input and then deal with saving it.
Another thing that has changed since Remi's article was published is that the WooCommerce variation meta data is no longer printed in a <Table> element... and is now a <div> element. This is important for how you structure your new content.
Here's is how you'd add a meta field to a variation:
// regular variable products
add_action( 'woocommerce_product_after_variable_attributes', 'add_to_variations_metabox', 10, 3 );
add_action( 'woocommerce_save_product_variation', 'save_product_variation', 20, 2 );
/*
* Add new inputs to each variation
*
* #param string $loop
* #param array $variation_data
* #return print HTML
*/
function add_to_variations_metabox( $loop, $variation_data, $variation ){
$custom = get_post_meta( $variation->ID, '_custom', true ); ?>
<div class="variable_custom_field">
<p class="form-row form-row-first">
<label><?php echo __( 'Custom Data:', 'plugin_textdomain' ); ?></label>
<input type="text" size="5" name="variation_custom_data[<?php echo $loop; ?>]" value="<?php echo esc_attr( $custom ); ?>" />
</p>
</div>
<?php
}
/*
* Save extra meta info for variable products
*
* #param int $variation_id
* #param int $i
* return void
*/
function save_product_variation( $variation_id, $i ){
// save custom data
if ( isset( $_POST['variation_custom_data'][$i] ) ) {
// sanitize data in way that makes sense for your data type
$custom_data = ( trim( $_POST['variation_custom_data'][$i] ) === '' ) ? '' : sanitize_title( $_POST['variation_custom_data'][$i] );
update_post_meta( $variation_id, '_custom', $custom_data );
}
}

I have found the following code from here working with WooCommerce 4.8.0
/**
* Create new fields for variations
*
*/
function hrx_variation_settings_fields( $loop, $variation_data, $variation ) {
// Text Field
woocommerce_wp_text_input(
array(
'id' => 'isbn_field[' . $variation->ID . ']',
'label' => __( 'ISBN', 'texdomain' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'ISBN', 'texdomain' ),
'value' => get_post_meta( $variation->ID, 'isbn_field', true )
)
);
}
add_action( 'woocommerce_product_after_variable_attributes', 'hrx_variation_settings_fields', 10, 3 );
/**
* Save new fields for variations
*
*/
function hrx_save_variation_settings_fields( $post_id ) {
// Text Field
$isbn_value = $_POST['isbn_field'][ $post_id ];
if( ! empty( $isbn_value ) ) {
update_post_meta( $post_id, 'isbn_field', esc_attr( $isbn_value ) );
}
}
add_action( 'woocommerce_save_product_variation', 'hrx_save_variation_settings_fields', 10, 2 );
WooCommerce : add custom fields to product variations

Related

Enhanced WooCommerce Custom Fields for Variations

Using the Remi Coulson tutorial, a custom field has been added for product variations.
This works, however the custom field is positioned by the add-to-cart button. I wish to position it within Additional Information tab. I have tried adding the front end code to the additional-information.php but it does not display.
<div class="woocommerce-variation-custom-text-field">
{{{ data.variation.text_field }}}
</div>
Added to functions.php to display variation
// Add Variation Settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
// Save Variation Settings
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
/**
* Create new fields for variations
*
*/
function variation_settings_fields( $loop, $variation_data, $variation ) {
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_text_field[' . $variation->ID . ']',
'label' => __( 'My Text Field', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_text_field', true )
)
);
}
/**
* Save new fields for variations
*
*/
function save_variation_settings_fields( $post_id ) {
// Text Field
$text_field = $_POST['_text_field'][ $post_id ];
if( ! empty( $text_field ) ) {
update_post_meta( $post_id, '_text_field', esc_attr( $text_field ) );
}
}
<?php
// Add New Variation Settings
add_filter( 'woocommerce_available_variation', 'load_variation_settings_fields' );
/**
* Add custom fields for variations
*
*/
function load_variation_settings_fields( $variations ) {
// duplicate the line for each field
$variations['text_field'] = get_post_meta( $variations[ 'variation_id' ], '_text_field', true );
return $variations;
}
Note that your code is a bit outdated since WooCommerce 3.
jQuery and some other changes are required to display the selected variation custom field value anywhere in a specific location on single product pages, specially outside the variation form.
In the example below the selected variation custom field value will be displayed on "Additional information" product tab after product attributes table.
Here is the complete revisited code:
// Add a custom field to variation settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
function variation_settings_fields( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input( array(
'id' => '_text_field[' . $loop . ']',
'label' => __( 'My Text Field', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_text_field', true ),
) );
}
// Save custom field value from variation settings
add_action( 'woocommerce_admin_process_variation_object', 'save_variation_settings_fields', 10, 2 );
function save_variation_settings_fields( $variation, $loop ) {
if( isset($_POST['_text_field'][$loop]) ) {
$variation->update_meta_data( '_text_field', sanitize_text_field($_POST['_text_field'][$loop]) );
}
}
// Add variation custom field to single variable product form
add_filter( 'woocommerce_available_variation', 'add_variation_custom_field_to_variable_form', 10, 3 );
function add_variation_custom_field_to_variable_form( $variation_data, $product, $variation ) {
$variation_data['text_field'] = $variation->get_meta('_text_field');
return $variation_data;
}
add_action( 'woocommerce_product_additional_information', 'add_html_container_to_display_selected_variation_custom_field' );
function add_html_container_to_display_selected_variation_custom_field( $product ){
echo '<div class="custom_variation-text-field"></div>';
}
// Display selected variation custom field value to product the tab
add_action( 'woocommerce_after_variations_form', 'display_selected_variation_custom_field_js' );
function display_selected_variation_custom_field_js(){
?>
<script type="text/javascript">
(function($){
$('form.cart').on('show_variation', function(event, data) {
$('.custom_variation-text-field').text(data.text_field);
}).on('hide_variation', function(event) {
$('.custom_variation-text-field').text('');
});
})(jQuery);
</script>
<?php
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Save Custom Field Data to Cart and Order of a Woocommerce product variation

We managed to put a custom field for variation products following Remi Corson guide here
At this point, we are able to show the custom text field in the single product page when users select the variation, but this is not enough in the purchase process since we need to:
A) Display this text in Cart and Checkout
B) Save this information so it shows in Thank You Page, Emails and Admin Order Edit Page
Something similar to Save and display product custom meta on WooCommerce orders and emails, but with product variations instead of simple products.
This is the code we added to our functions.php to add the custom field to the product variations
// Add Variation Settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
// Save Variation Settings
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
/**
* Create new fields for variations
*
*/
function variation_settings_fields( $loop, $variation_data, $variation ) {
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_text_field[' . $variation->ID . ']',
'label' => __( 'My Text Field', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_text_field', true )
)
);
// Hidden field
woocommerce_wp_hidden_input(
array(
'id' => '_hidden_field[' . $variation->ID . ']',
'value' => 'hidden_value'
)
);
}
/**
* Save new fields for variations
*
*/
function save_variation_settings_fields( $post_id ) {
// Text Field
$text_field = $_POST['_text_field'][ $post_id ];
if( ! empty( $text_field ) ) {
update_post_meta( $post_id, '_text_field', esc_attr( $text_field ) );
}
// Hidden field
$hidden = $_POST['_hidden_field'][ $post_id ];
if( ! empty( $hidden ) ) {
update_post_meta( $post_id, '_hidden_field', esc_attr( $hidden ) );
}
}
// Add New Variation Settings
add_filter( 'woocommerce_available_variation', 'load_variation_settings_fields' );
/**
* Add custom fields for variations
*
*/
function load_variation_settings_fields( $variations ) {
// duplicate the line for each field
$variations['text_field'] = get_post_meta( $variations[ 'variation_id' ], '_text_field', true );
return $variations;
}
So the goal here is how can we show this custom field for each variation in the Cart and Checkout below the items (Something like the image below - Look at the Shipping delay notice)
And to save that custom field info that each variation has to the Thank You Page, Emails and Order Page (We did it for simple products with this code, but this doesn't work for variable ones)
// Save and display "Custom Field for Simple Products" on order items everywhere
add_filter( 'woocommerce_checkout_create_order_line_item', 'action_wc_checkout_create_order_line_item', 10, 4 );
function action_wc_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
// Get the Custom Field
$value = $values['data']->get_meta( 'custom_field_for_simple_products' );
if( ! empty( $value ) ) {
// Save it and display it
$item->update_meta_data( __( 'Custom Fields', 'woocommerce' ), $value );
}
}
Please help!!
Updated
There are some mistakes in your codeā€¦ The following revisited code will solve your issue:
// Display Variation custom fields (admin)
add_action( 'woocommerce_product_after_variable_attributes', 'display_variation_setting_custom_fields', 10, 3 );
function display_variation_setting_custom_fields( $loop, $variation_data, $variation ) {
echo '<div>';
woocommerce_wp_text_input( array( // Text Field
'id' => "_text_field[$loop]",
'label' => __("My Text Field", "woocommerce"),
'placeholder' => "http://",
'desc_tip' => true,
'description' => __("Enter the custom value here.", "woocommerce"),
'wrapper_class' => 'form-row form-row-full',
'value' => get_post_meta( $variation->ID, '_text_field', true ),
) );
woocommerce_wp_hidden_input( array( // Hidden field
'id' => "_hidden_field[$loop]",
'value' => 'hidden_value',
) );
echo '</div>';
}
// Save Variation custom fields
add_action( 'woocommerce_save_product_variation', 'save_variation_custom_fields', 10, 2 );
function save_variation_custom_fields( $variation_id, $i ) {
// Save Text Field
if( isset( $_POST['_text_field'][$i] ) && ! empty( $_POST['_text_field'][$i] ) )
update_post_meta( $variation_id, '_text_field', sanitize_text_field( $_POST['_text_field'][$i] ) );
// Save Hidden Field
if( isset( $_POST['_hidden_field'][$i] ) && ! empty( $_POST['_hidden_field'][$i] ) )
update_post_meta( $variation_id, '_hidden_field', esc_attr( $_POST['_hidden_field'][$i] ) );
}
// Include our variation custom field
add_filter( 'woocommerce_available_variation', 'include_variation_custom_field', 10, 3) ;
function include_variation_custom_field( $data, $product, $variation ) {
$data['text_field'] = $variation->get_meta( '_text_field' );
return $data;
}
// Save and display "Custom Field for Simple Products" on order items everywhere
add_filter( 'woocommerce_checkout_create_order_line_item', 'action_wc_checkout_create_order_line_item_2', 10, 4 );
function action_wc_checkout_create_order_line_item_2( $item, $cart_item_key, $values, $order ) {
// Get the Custom Field
$value = $values['data']->get_meta( '_text_field' );
if( ! empty( $value ) ) {
// Save it and display it
$item->update_meta_data( __( 'Custom Field', 'woocommerce' ), $value );
}
}
Code goes in functions.php file of your active child theme (or active theme) . Tested and works.
Related: Save and display product custom meta on WooCommerce orders and emails
Somme screenshots
On admin product variations settings:
On order received page (thankyou):
On admin edit orders pages:

Displaying custom field of product variations within Woocommerce orders and emails

I successfully added a custom field for product variations within the backend of WooCommerce and was able to display its value. I'd like to contain this value within order and emails as well.
//Display Fields in admin on product edit screen
add_action( 'woocommerce_product_after_variable_attributes', 'woo_variable_fields', 10, 3 );
//Save variation fields values
add_action( 'woocommerce_save_product_variation', 'save_variation_fields', 10, 2 );
// Create new fields for variations
function woo_variable_fields( $loop, $variation_data, $variation ) {
echo '<div class="variation-custom-fields">';
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_text_field['. $loop .']',
'label' => __( 'additional fees (e.g. monthly fee)', 'woocommerce' ),
'placeholder' => '',
//'desc_tip' => true,
'wrapper_class' => 'form-row form-row-first',
//'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta($variation->ID, '_text_field', true)
)
);
echo "</div>";
}
/** Save new fields for variations */
function save_variation_fields( $variation_id, $i) {
// Text Field
$text_field = stripslashes( $_POST['_text_field'][$i] );
update_post_meta( $variation_id, '_text_field', esc_attr( $text_field ) );
}
// Custom Product Variation
add_filter( 'woocommerce_available_variation', 'custom_load_variation_settings_products_fields' );
function custom_load_variation_settings_products_fields( $variations ) {
$variations['variation_custom_field'] = get_post_meta( $variations[ 'variation_id' ], '_text_field', true );
return $variations;
}
I'm using the following to display the custom field's value within the cart.
add_filter( 'woocommerce_get_item_data', 'display_custom_field_as_item_data', 20, 2 );
function display_custom_field_as_item_data( $cart_data, $cart_item ) {
if( $value = get_post_meta( $cart_item['data']->get_id(), '_text_field', true ) ){
$cart_data[] = array(
'name' => __( 'Additional Monthly Fee', 'woocommerce' ),
'value' => sanitize_text_field( $value )
);
}
return $cart_data;
}
Further as for now I'm displaying its value below the product price / total of each item within cart/checkout template with the following
echo get_post_meta( $_product->get_id(), '_text_field', true );
How about displaying the value of this field within orders and emails?
Updated: To display that in order pages and email notifications try the following additional functions (I have made some changes in the woocommerce_get_item_data hooked function, so you need to replace it with the following one):
// Save custom field value in cart item
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_field_in_cart_object', 30, 3 );
function save_custom_field_in_cart_object( $cart_item_data, $product_id, $variation_id ) {
// Get the correct Id to be used
$the_id = $variation_id > 0 ? $variation_id : $product_id;
if( $value = get_post_meta( $the_id, '_text_field', true ) )
$cart_item_data['custom_data'] = sanitize_text_field( $value );
return $cart_item_data;
}
// Display on cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'display_custom_field_as_item_data', 20, 2 );
function display_custom_field_as_item_data( $cart_data, $cart_item ) {
if( isset( $cart_item['custom_data'] ) ){
$cart_data[] = array(
'name' => __( 'Additional Monthly Fee', 'woocommerce' ),
'value' => $cart_item['custom_data']
);
}
return $cart_data;
}
// Save custom field value in order items meta data
add_action( 'woocommerce_add_order_item_meta', 'add_custom_field_to_order_item_meta', 20, 3 );
function add_custom_field_to_order_item_meta( $item_id, $values, $cart_item_key ) {
if( isset( $values['custom_data'] ) )
wc_add_order_item_meta( $item_id, __( 'Additional Monthly Fee', 'woocommerce' ), $values['custom_data'] );
}
Code goes in function.php file of your active child theme (or theme). Tested and works.
It will display the custom field label and value in all Order pages and in email notifications too.

WooComerce Custom Field show only in default site language?

I have one issue that dont know how to resolve myself, so need your help. I have inserted Custom Field into my WooCommerce site product page. I have used this code to show my custom field bellow "Add to Cart" page, and also bellow product into cart page.
// Display Product settings Fields
add_action( 'woocommerce_product_options_general_product_data',
'woo_add_custom_general_fields' );
function woo_add_custom_general_fields() {
woocommerce_wp_text_input( array(
'id' => '_pd_number',
'label' => __( 'Delivery Time', 'woocommerce' ),
'placeholder' => 'Some text here',
'desc_tip' => 'true',
'description' => __( 'Enter some text', 'woocommerce' )
));
}
// Save Product settings Fields
add_action( 'woocommerce_process_product_meta',
'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields_save( $post_id ){
$pd_number = $_POST['_pd_number'];
if( !empty( $pd_number ) )
update_post_meta( $post_id, '_pd_number', esc_attr( $pd_number ) );
}
// Show text in Product Page
add_action( 'woocommerce_after_add_to_cart_button',
'add_cf_before_addtocart_in_single_products', 1, 0 );
function add_cf_before_addtocart_in_single_products()
{
global $product;
$pd_number = get_post_meta( $product->get_id(), '_pd_number', true );
if( !empty( $pd_number ) )
echo '<div class="pd-number">'. $pd_number .'</div><br>';
}
// Displaying the product custom field in the Cart items
add_filter( 'woocommerce_cart_item_name', 'add_cf_after_cart_item_name', 10,
3 );
function add_cf_after_cart_item_name( $name_html, $cart_item, $cart_item_key
)
{
$product_id = $cart_item['product_id'];
if( $cart_item['variation_id'] > 0 )
$product_id = $cart_item['variation_id'];
$pd_number = get_post_meta( $product_id, '_pd_number', true );;
if( !empty( $pd_number ) )
$name_html .= '<br><span class="pd-number">'.$pd_number .'</span>';
return $name_html;
}
but show only on my default site language Dansk. If choise English from top bar, custom field is not shown. I use WPML as language plugin. Any help ?
In this image, if you put the blank custom field in other languages then it does not appear in front end

Show custom field value in cart in WooCommerce

I'm using Wordpress together with WooCommerce for my shop.
I want to output the value of my custom field in my cart and in the email order confirmation.
I have created a custom field in my functions.php:
// Display Fields
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );
// Save Fields
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
// Input
woocommerce_wp_text_input(
array(
'id' => '_gram',
'label' => __( 'somelabel', 'woocommerce' ),
'placeholder' => '',
'description' => __( 'sometext', 'woocommerce' ),
'type' => 'number',
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
echo '</div>';
}
function woo_add_custom_general_fields_save( $post_id ){
// Number Field
$woocommerce_number_field = $_POST['_gram'];
if( !empty( $woocommerce_number_field ) )
update_post_meta( $post_id, '_gram', esc_attr( $woocommerce_number_field ) );
}
On my pages I'm using:
get_post_meta( get_the_ID(), '_gram', true );
To show the value and that work perfect.
Now I want to show this same value under the product name in my cart and in the email confirmations.
But I cant figure out how to do this.
Does anyone knows how to do this?
Well it's a long process, you have to implement two filters & one action to accomplish this.
Also there is a plugin for this exact purpose along with lot of other options related to woocommerce custom fields.
Here is the direct solution for your question.
/**
* Here we are trying to add your custom data as Cart Line Item
* SO that we can add this custom data on your cart, checkout, order and email later
*/
function save_custom_data( $cart_item_data, $product_id ) {
$custom_data = get_post_meta( $product_id, '_gram', true );
if( $custom_data != null && $custom_data != "" ) {
$cart_item_data["gram"] = $custom_data;
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_data', 10, 2 );
/**
* Here we are trying to display that custom data on Cart Table & Checkout Order Review Table
*/
function render_custom_data_on_cart_checkout( $cart_data, $cart_item = null ) {
$custom_items = array();
/* Woo 2.4.2 updates */
if( !empty( $cart_data ) ) {
$custom_items = $cart_data;
}
if( isset( $cart_item["gram"] ) ) {
$custom_items[] = array( "name" => "Gram", "value" => $cart_item["gram"] );
}
return $custom_items;
}
add_filter( 'woocommerce_get_item_data', 'render_custom_data_on_cart_checkout', 10, 2 );
/**
* We are adding that custom data ( gram ) as Order Item Meta,
* which will be carried over to EMail as well
*/
function save_custom_order_meta( $item_id, $values, $cart_item_key ) {
if( isset( $values["gram"] ) ) {
wc_add_order_item_meta( $item_id, "Gram", $values["gram"] );
}
}
add_action( 'woocommerce_add_order_item_meta', 'save_custom_order_meta', 10, 3 );

Categories