WooCommerce custom fields output - wordpress

I have created custom text field, but I am not able to output it on the single product page using action hook...
I would be really thankfull if anybody can provide solution ?
My Code (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">';
// Custom fields will be created here...
woocommerce_wp_text_input(
array(
'id' => '_text_field',
'label' => __( 'My Text Field', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' )
)
);
echo '</div>';
}
function woo_add_custom_general_fields_save( $post_id ){
// Text Field
$woocommerce_text_field = $_POST['_text_field'];
if( !empty( $woocommerce_text_field ) )
update_post_meta( $post_id, '_text_field', esc_attr( $woocommerce_text_field ) );
}
add_action( 'woocommerce_single_product_summary', 'output_custom_fields' );
function output_custom_fields() {
echo get_post_meta( $post->ID, '_text_field', true );
}
Thanks!
Denis

As #MirzaP says in comment, $post is not defined in the function output_custom_fields(). So $post->ID can not work
To make it work (be able to get the post object in the function)
function output_custom_fields() {
global $post;
echo get_post_meta( $post->ID, '_text_field', true );
}
Don't forget the third parameter of your hooked action, that will sets the priority. These priorities can be found in the Woocommerce template, use the right priority according of where you want to place your meta data.
/**
* woocommerce_single_product_summary hook
*
* #hooked woocommerce_template_single_title - 5
* #hooked woocommerce_template_single_price - 10
* #hooked woocommerce_template_single_excerpt - 20
* #hooked woocommerce_template_single_add_to_cart - 30
* #hooked woocommerce_template_single_meta - 40
* #hooked woocommerce_template_single_sharing - 50
*/
So if you want your custom data to be shown right after the price, you need to set the priority with an integrer between 11 and 19
add_action('woocommerce_single_product_summary', 'output_custom_fields', 15);

Related

Add hook for variation header in variations list when editing a product

i add custom field in varation and i wiil be its display in header varation
enter image description here
the code for custom field i take in businessbloomer and is:
/**
* #snippet Add Custom Field to Product Variations - WooCommerce
* #how-to Get CustomizeWoo.com FREE
* #author Rodolfo Melogli
* #compatible WooCommerce 4.6
* #donate $9 https://businessbloomer.com/bloomer-armada/
*/
// -----------------------------------------
// 1. Add custom field input # Product Data > Variations > Single Variation
add_action( 'woocommerce_variation_options_pricing', 'bbloomer_add_custom_field_to_variations', 10, 3 );
function bbloomer_add_custom_field_to_variations( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input( array(
'id' => 'custom_field[' . $loop . ']',
'class' => 'short',
'label' => __( 'Custom Field', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, 'custom_field', true )
) );
}
and i do action to appear in header varation in here code:
/**
* Admin variation list needs clarity.
*
* #param \WP_Post $variation .
* #see https://github.com/woocommerce/woocommerce/issues/21362
* #since 3.6.0
*/
add_action( 'woocommerce_variation_header', function( \WP_Post $variations ) {
$variations['custom_field'] = get_post_meta( $variations[ 'variation_id' ], 'custom_field', true ) ;
if ( $variations['custom_field'] ) {
printf( 'SKU: <strong>%s</strong>', esc_attr( $variations['custom_field'] ) );
}
} );

Create a custom field on WooCommerce checkout if product category equals x

so I'm looking to create/show a couple of custom fields on the checkout page of my WooCommerce page as long as a product with a certain category is in the cart. The values of these fields are only necessary for me to access in the order on the backend afterwards, and does not need to be added to the order e-mail confirmation to the customer.
Any pointers? If it helps things, I'm using ACF on my website.
Thanks in advance!
You need to do the following:
Detect if the existing products in cart is in your category
Add the fields on checkout if it matches your condition.
Validate and save the data
Display it on the backend.
This is already outlined on the docs, and you might want to read it:
https://woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/#adding-a-custom-special-field
Here is an example function to detect if the cart contains a certain product within a defined category
// functions.php
function cat_in_cart( $cat_slug ) {
$cat_in_cart = false;
$cart = WC()->cart->get_cart();
if ( !$cart ) {
return $cat_in_cart;
}
foreach( $cart as $cart_item_key => $cart_item ) {
if ( has_term( $cat_slug, 'product_cat', $cart_item['product_id'] )) {
$cat_in_cart = true;
break;
}
}
return $cat_in_cart;
}
To add a field on checkout (Link to docs):
// functions.php
/**
* Add the field to the checkout
*/
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );
function my_custom_checkout_field( $checkout ) {
if ( cat_in_cart( 'your_category_slug' ) ) {
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>';
}
}
After that, save the field on 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' );
}
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'] ) );
}
}
Lastly, display it on the dashboard:
/**
* 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>';
}

custom field value isn't stored in variation_data object

i have following issue with woocommerce/dokan:
I created a custom field for product variation:
custom field in wordpress backend
It works fine, the values are storing and i can change the value at the backend. Therefor i added following lines of code into function.php of theme file:
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 ) );
}
}
// 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 far, so good. I can set a value and the value can be saved over the backend.
Now i want to change the custom field for this product variation in dokan vendor dashboard. I duplicated html-product-variation.php file into child theme and added the new field:
dokan vendor dashboard product variation
with following code:
<div>
<p class="dokan-form-group">
<label><?php esc_html_e( 'Custom Textfield', 'dokan' ); ?></label>
<textarea class="dokan-form-control" name="_text_field[<?php echo esc_attr( $loop ); ?>]" rows="3" style="width:100%;"><?php echo isset( $variation_data['_text_field'] ) ? esc_textarea( $variation_data['_text_field'] ) : ''; ?></textarea>
</p>
</div>
The problem is, that the value, which i set in the backend isn't shown and if i inspect the variation_data object there is no key in the array which says "_text_field". How can i store/update variation_data object?
I hope it's understandable which issue i'm facing here and look forward to some help :)
Best wishes,
Florian

Generate WooCommerce coupon when comment review is approved

I'm trying to generate a coupon code for customer once his review comment in woocommerce product is approved. I have the whole code ready but once comment is approved nothing happen.
My code only works with comment_post hook but not with the comment_unapproved_to_approved hook. Any advice?
function action_comment_post_coupon( $comment, $comment_ID, $comment_approved, $commentdata ) {
if ( isset ( $commentdata['comment_author_email'] ) ) {
// Get author email
$author_email = $commentdata['comment_author_email'];
if ( is_email( $author_email ) ) {
$value = random_int(100000, 999999);
$customer = $comment->comment_author_email;
$coupon_code = $value; // Code
$amount = '20'; // Amount
$discount_type = 'percent'; // Type: fixed_cart, percent, fixed_product, percent_product
$coupon = array(
'post_title' => $coupon_code,
'post_content' => '',
'post_status' => 'draft',
'post_author' => 1,
'post_type' => 'shop_coupon'
);
$new_coupon_id = wp_insert_post( $coupon );
// Add meta
update_post_meta( $new_coupon_id, 'discount_type', $discount_type );
update_post_meta( $new_coupon_id, 'coupon_amount', $amount );
update_post_meta( $new_coupon_id, 'individual_use', 'yes' );
update_post_meta( $new_coupon_id, 'customer_email', $author_email );
update_post_meta( $new_coupon_id, 'product_ids',$product_ids );
update_post_meta( $new_coupon_id, 'exclude_product_ids', '' );
update_post_meta( $new_coupon_id, 'usage_limit', '1' );
update_post_meta( $new_coupon_id, 'expiry_date', strtotime("+14 days") );
update_post_meta( $new_coupon_id, 'apply_before_tax', 'yes' );
update_post_meta( $new_coupon_id, 'free_shipping', 'no' );
unset($product_ids);
}
}
}
add_action( 'comment_unapproved_to_approved', 'action_comment_post_coupon', 10, 4 );
"My code only works with comment_post hook but not with the comment_unapproved_to_approved hook"
As you can see the comment_post hook contains 3 params
/**
* Fires immediately after a comment is inserted into the database.
*
* #since 1.2.0
* #since 4.5.0 The `$commentdata` parameter was added.
*
* #param int $comment_ID The comment ID.
* #param int|string $comment_approved 1 if the comment is approved, 0 if not, 'spam' if spam.
* #param array $commentdata Comment data.
*/
function action_comment_post( $comment_ID, $comment_approved, $commentdata ) {
// Do something
}
add_action( 'comment_post', 'action_comment_post', 10, 3 );
See: do_action( 'comment_post', int $comment_ID, int|string $comment_approved, array $commentdata )
While the comment_unapproved_to_approved hook contains only 1 which is $comment, therefore just changing hookname is not enough.
See: do_action( "comment_{$old_status}_to_{$new_status}", WP_Comment $comment )
So to answer your question you get:
/**
* Fires when the comment status is in transition from one specific status to another.
*
* The dynamic portions of the hook name, `$old_status`, and `$new_status`,
* refer to the old and new comment statuses, respectively.
*
* Possible hook names include:
*
* - `comment_unapproved_to_approved`
* - `comment_spam_to_approved`
* - `comment_approved_to_unapproved`
* - `comment_spam_to_unapproved`
* - `comment_unapproved_to_spam`
* - `comment_approved_to_spam`
*
* #since 2.7.0
*
* #param WP_Comment $comment Comment object.
*/
function action_comment_unapproved_to_approved( $comment ) {
// When isset
if ( isset ( $comment->comment_author_email ) ) {
// Get author email
$author_email = $comment->comment_author_email;
// Is email
if ( is_email( $author_email ) ) {
// Get an emty instance of the WC_Coupon Object
$coupon = new WC_Coupon();
// Generate a non existing coupon code name
$coupon_code = random_int( 100000, 999999 ); // OR generate_coupon_code();
$discount_type = 'percent';
$coupon_amount = '20'; // Amount
// Set the necessary coupon data (since WC 3+)
$coupon->set_code( $coupon_code );
$coupon->set_discount_type( $discount_type );
$coupon->set_amount( $coupon_amount );
$coupon->set_individual_use( true );
$coupon->set_usage_limit( 1 );
$coupon->set_email_restrictions( array( $author_email ) );
$coupon->set_date_expires( strtotime( '+14 days' ) );
$coupon->set_free_shipping( true );
// Create, publish and save coupon (data)
$coupon->save();
}
}
}
add_action( 'comment_unapproved_to_approved', 'action_comment_unapproved_to_approved', 10, 1 );
Note: since WooCommerce 3, your code is a bit outdated. Instead you should better use the available WC_Coupon setter methods.
All information about this can be found via WC_Coupon

WooCommerce 4.0 custom checkout & ACF field value on email, admin order, and thank you page

I'm having a hard time printing my custom field value to the email notifications, order admin and thank you page. I've browsed through StackOverflow, tried every single answer I found but unfortunately not working and I couldn't figure out the problem:
I am trying to pass the value of the additional checkout field, it only prints the strong label with a blank value, and in the emails nothing shows, here is my code so far:
//new pickup location checkout field
add_action( 'woocommerce_before_order_notes', 'pickup_location_custom_checkout_field' );
function pickup_location_custom_checkout_field( $checkout ) {
echo '<div><h3>' . __('Pick-up location') . '</h3>';
woocommerce_form_field( 'pick_up_location', array(
'type' => 'text',
'class' => array('notes'),
'label' => __('<span style="color:red">[IMPORTANT]</span> Where should we meet you?'),
'placeholder' => __('Please enter your accomodation name or the nearest pick-up point if not accessible by car'),
'required' => true,
), $checkout->get_value( 'pick_up_location' ));
echo '</div>';
}
// Save the pickup location data to the order meta
add_action( 'woocommerce_checkout_create_order', 'pickup_location_checkout_field_update_order_meta' );
function pickup_location_checkout_field_update_order_meta( $order_id ) {
if (!empty($_POST['pick_up_location'])) {
update_post_meta( $order_id, 'Pick-up location', sanitize_text_field( $_POST['pick_up_location']));
}
}
// Display 'pickup location' on the order edit page (backend)
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'pickup_location_checkout_field_order_page', 10, 1 );
function pickup_location_checkout_field_order_page($order){
global $post_id;
$order = new WC_Order( $post_id );
echo '<p><strong style="color:red">'.__('Pickup Location').':</strong> ' . get_post_meta($order->get_id(), '_pick_up_location', true ) . '</p>';
// Display 'pickup location' in "Order received" and "Order view" pages (frontend)
add_action( 'woocommerce_order_details_after_order_table', 'display_client_pickup_data_in_orders', 10 );
function display_client_pickup_data_in_orders( $order ) {
global $post_id;
$order = new WC_Order( $post_id );
echo '<p><strong style="color:red">'.__('Pickup Location').':</strong> ' . get_post_meta($order->get_id(), '_pick_up_location', true ) . '</p>';
}
// Display 'pickup location data' in Email notifications
add_filter( 'woocommerce_email_order_meta_fields', 'display_client_pickup_data_in_emails', 10, 3 );
function display_client_pickup_data_in_emails( $fields, $sent_to_admin, $order ) {
$fields['Pickup Location'] = array(
'label' => __( 'Pickup Location' ),
'value' => get_post_meta( $order->get_id(), 'pick_up_location', true ),
);
return $fields;
}
No matter what I try, the code only prints the label without any value from the checkout form.
I know this question has been asked many times, but I tried every single answer for over 6 days without any luck. I also need to mention that I am using Woocommerce Bookings in this project.
Thanks for your help
[Update:] Saving and displaying ACF field in the cart, admin order, customer order, checkout, and emails.
Thanks to #7uc1f3r for the detailed explanation, his answer helped me to display the ACF field in a similar way, it is also based on This answer from #LoicTheAztec.
Displaying custom field on the product page above ATC:
// Displaying Pick-up time custom field value in single product page
add_action( 'woocommerce_before_add_to_cart_button', 'add_pickup_time_custom_field', 0 );
function add_pickup_time_custom_field() {
global $product;
//(compatibility with WC +3)
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
echo "<div class='pickup-time-atc'>";
echo "<span>Pick-up time: </span>";
echo get_field( 'pick_up_time', $product_id );
echo "</div>";
return true;
}
Displaying custom field value in single product page
Saving Pick-up time custom field into cart and session
// Saving Pick-up time custom field into cart and session
add_filter( 'woocommerce_add_cart_item_data', 'save_pickup_time_custom_field', 10, 2 );
function save_pickup_time_custom_field( $cart_item_data, $product_id ) {
$custom_field_value = get_field( 'pick_up_time', $product_id, true );
if( !empty( $custom_field_value ) )
{
$cart_item_data['pick_up_time'] = $custom_field_value;
}
return $cart_item_data;
}
Render Pick-up time custom field meta on cart and checkout
// Render Pick-up time meta on cart and checkout
add_filter( 'woocommerce_get_item_data', 'render_pickuptime_meta_on_cart_and_checkout', 10, 2 );
function render_pickuptime_meta_on_cart_and_checkout( $cart_data, $cart_item ) {
$custom_items = array();
// Woo 2.4.2 updates
if( !empty( $cart_data ) ) {
$custom_items = $cart_data;
}
if( isset( $cart_item['pick_up_time'] ) ) {
$custom_items[] = array( "name" => "Pickup time", "value" => $cart_item['pick_up_time'] );
}
return $custom_items;
}
Render custom field meta on cart and checkout
Add custom field meta to order admin details
// Add pickup time custom field meta to order admin
add_action( 'woocommerce_checkout_create_order_line_item', 'pickuptime_checkout_create_order_line_item', 10, 4 );
function pickuptime_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
if( isset( $values['pick_up_time'] ) ) {
$item->add_meta_data(
__( 'Pickup time' ),
$values['pick_up_time'],
true
);
}
}
Add custom field meta to order admin details
Add pickup time custom field meta to emails
// Add pickup time custom field meta to emails
add_filter( 'woocommerce_order_item_name', 'pickuptime_order_item_emails', 10, 2 );
function pickuptime_order_item_emails( $product_name, $item ) {
if( isset( $item['pick_up_time'] ) ) {
$product_name .= sprintf(
'<ul"><li>%s: %s</li></ul>',
__( '<span style="color:red !important">Pickup time</span>' ),
esc_html( $item['pick_up_time'] )
);
}
return $product_name;
}
Add pickup time custom field meta to emails
Please comment if you see any errors or ways to improve,
Thanks.
Woocommerce 4.0.0 and Wordpress 5.3.2
Go through your code step by step
update_post_meta( $order_id, 'Pick-up location', sanitize_text_field( $_POST['pick_up_location']));
echo '<p><strong style="color:red">'.__('Pickup Location').':</strong> ' . get_post_meta($order->get_id(), '_pick_up_location', true ) . '</p>';
'value' => get_post_meta( $order->get_id(), 'pick_up_location', true ),
You use Pick-up location, _pick_up_location & pick_up_location as meta_key
while this should be 3x the same value.
You also miss a closing tag by pickup_location_checkout_field_order_page function.
You also use wrong parameters with some hooks, etc..
Try this instead
//new pickup location checkout field
add_action( 'woocommerce_before_order_notes', 'pickup_location_custom_checkout_field' );
function pickup_location_custom_checkout_field( $checkout ) {
echo '<div><h3>' . __('Pick-up location') . '</h3>';
woocommerce_form_field( 'pick_up_location', array(
'type' => 'text',
'class' => array('notes'),
'label' => __('<span style="color:red">[IMPORTANT]</span> Where should we meet you?'),
'placeholder' => __('Please enter your accomodation name or the nearest pick-up point if not accessible by car'),
'required' => true,
), $checkout->get_value( 'pick_up_location' ));
echo '</div>';
}
// Save the pickup location data to the order meta
add_action( 'woocommerce_checkout_create_order', 'pickup_location_checkout_field_update_order_meta', 10, 2 );
function pickup_location_checkout_field_update_order_meta( $order, $data ) {
if ( !empty( $_POST['pick_up_location']) ) {
$order->update_meta_data( '_pick_up_location', sanitize_text_field( $_POST['pick_up_location'] ) ); // Order meta data
}
}
// Display 'pickup location' on the order edit page (backend)
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'pickup_location_checkout_field_order_page', 10, 1 );
function pickup_location_checkout_field_order_page( $order ) {
$pick_up_location = $order->get_meta( '_pick_up_location' );
echo '<p><strong style="color:red">'.__('Pickup Location').':</strong> ' . $pick_up_location . '</p>';
}
// Display 'pickup location' in "Order received" and "Order view" pages (frontend)
add_action( 'woocommerce_order_details_after_order_table', 'display_client_pickup_data_in_orders', 10 );
function display_client_pickup_data_in_orders( $order ) {
$pick_up_location = $order->get_meta( '_pick_up_location' );
echo '<p><strong style="color:red">'.__('Pickup Location').':</strong> ' . $pick_up_location . '</p>';
}
// Display 'pickup location data' in Email notifications
add_filter( 'woocommerce_email_order_meta_fields', 'display_client_pickup_data_in_emails', 10, 3 );
function display_client_pickup_data_in_emails( $fields, $sent_to_admin, $order ) {
$fields['Pickup Location'] = array(
'label' => __( 'Pickup Location' ),
'value' => $order->get_meta( '_pick_up_location' ),
);
return $fields;
}

Resources