I added a field to the product display page. I did some research but was not successful.
I have a form element like the one below, it may be text in this picture.
https://prnt.sc/vql93m
I want to save a field as a post meta while creating the product.
Then I want to show the relevant meta on the order page, actually I did it partially, but I can't save the relevant data.
https://prnt.sc/vqlbfs
And I can only add to cart on the single product display page, all other sections should be removed.
https://prnt.sc/vql8mj
Hooks and codes I used.
add_action('woocommerce_before_add_to_cart_button', 'woocommerce_custom_fields_display');
function woocommerce_custom_fields_display()
{
?>
<label>Product type:</label><br><input type="text" id="product-type" name="product-type"><br><br>
<?php
}
add_action( 'woocommerce_before_order_itemmeta', 'so_32457241_before_order_itemmeta', 10, 3 );
function so_32457241_before_order_itemmeta( $item_id, $item, $_product ){
$order = json_decode( $item );
echo get_post_meta( $order['order_id'], 'product-type', true );
}
add_action( 'woocommerce_new_order', 'custom_woocommerce_order' );
function custom_woocommerce_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
var_dump( $order );
var_dump( $_POST );
}
add_action('woocommerce_add_to_cart', 'custome_add_to_cart');
function custome_add_to_cart() {
$p_id=$_POST['product-type'];
WC()->cart->add_to_cart( $p_id );
}
Related
I am trying to add a custom user meta field to the order meta data.
And I want to add this when I am changing my order status to "wordt-verwerkt" which is a custom order status I added with the WooCommerce plugin for custom order statuses.
I tried to use the code from this post, but I am getting an error when I change my order status.
(I also tried it with the status "processing", and didn't have any success neither)
What I have now is the following code:
add_action( 'woocommerce_order_status_wordt-verwerkt', 'add_order_meta_from_custom_user_meta', 10, 2 );
function add_order_meta_from_custom_user_meta( $order, $data ) {
$user_id = $order->get_user_id(); // Get the user id
if( $WefactEmail = get_user_meta( $user_id, 'KVK_nummer_2', true ) ) {
$order->update_meta_data( 'WeFact_email', $WefactEmail );
}
if( isset($WefactEmail) ) {
$order->save();
}
}
There are some mistakes in your code (the hooked function arguments are wrong).
See the related source code for this composite hook located in WC_Order status_transition() method (on line 363):
do_action( 'woocommerce_order_status_' . $status_transition['to'], $this->get_id(), $this );
where $this is $order (the WC_Order Object) and $this->get_id() is $order_id (the order Id).
Use instead the following:
add_action( 'woocommerce_order_status_wordt-verwerkt', 'add_order_meta_from_custom_user_meta', 10, 2 );
function add_order_meta_from_custom_user_meta( $order_id, $order ) {
$user_id = $order->get_user_id(); // Get the user id
$wf_email = get_user_meta( $user_id, 'KVK_nummer_2', true );
if( ! empty($wf_email) ) {
$order->update_meta_data( 'WeFact_email', $wf_email );
$order->save();
}
}
or also this works too:
add_action( 'woocommerce_order_status_wordt-verwerkt', 'add_order_meta_from_custom_user_meta', 10, 2 );
function add_order_meta_from_custom_user_meta( $order_id, $order ) {
$user_id = $order->get_user_id(); // Get the user id
$wf_email = get_user_meta( $user_id, 'KVK_nummer_2', true );
if( ! empty($wf_email) ) {
update_post_meta( $order_id, 'WeFact_email', $wf_email );
}
}
Code goes in functions.php file of the active child theme (or active theme). both should work.
For processing status, replace:
add_action( 'woocommerce_order_status_wordt-verwerkt', 'add_order_meta_from_custom_user_meta', 10, 2 );
with:
add_action( 'woocommerce_order_status_processing', 'add_order_meta_from_custom_user_meta', 10, 2 );
I successfully created a ACF custom field in WooCommerce within my product variations in the backend. The field is properly shown within each variation.
But after editing this or other fields within the variations I can't save the whole variations tab anymore. The loading/saving indicator circle continues to rotate indefinitely. And the custom field is not showing in the single product variation in frontend.
What I did, was to add the following code to my functions.php:
/* ACF filter for Variations */
// Render fields at the bottom of variations - does not account for field group order or placement.
$GLOBALS['wc_loop_variation_id'] = null;
function is_field_group_for_variation($field_group, $variation_data, $variation_post) {
return (preg_match( '/Variation/i', $field_group['title'] ) == true);
}
add_action( 'woocommerce_product_after_variable_attributes', function( $loop_index, $variation_data, $variation_post ) {
$GLOBALS['wc_loop_variation_id'] = $variation_post->ID;
foreach ( acf_get_field_groups() as $field_group ) {
if ( is_field_group_for_variation( $field_group, $variation_data, $variation_post ) ) {
acf_render_fields( $variation_post->ID, acf_get_fields( $field_group ) );
}
}
$GLOBALS['wc_loop_variation_id'] = null;
}, 10, 3 );
add_action( 'woocommerce_save_product_variation', function( $variation_id, $loop_index ) {
if ( !isset( $_POST['acf_variation'][$variation_id] ) ) {
return;
}
$_POST['acf'] = $_POST['acf_variation'][$variation_id];
acf()->input->save_post( $variation_id );
}, 10, 2 );
add_filter( 'acf/prepare_field', function ( $field ) {
if ( !$GLOBALS['wc_loop_variation_id'] ) {
return $field;
}
$field['name'] = preg_replace( '/^acf\[/', 'acf_variation[' . $GLOBALS['wc_loop_variation_id'] . '][', $field['name'] );
return $field;
}, 10, 1);
//add ACF rule
add_filter('acf/location/rule_values/post_type', 'acf_location_rule_values_Post');
function acf_location_rule_values_Post( $choices ) {
$choices['product_variation'] = 'Product Variation';
//print_r($choices);
return $choices;
}
/* End */
Any help would be appreciated.
acf()->input->save_post( $variation_id );
Should be
do_action( 'acf/save_post', $variation_id );
Credit to onoweb from here https://support.advancedcustomfields.com/forums/topic/acf-on-product-variations-almost-works/
I am creating an event ticketing WordPress theme and I am using WooCommerce and Advanced custom fields (ACF) plugins.
I want to update a custom post type called event. With the stock of a specific ticket. That way my client does not need to look at the woo-commerce products page but can just simply open an "Event"
I tried using the update_post_meta hook but that only works when an admin updates the product in the admin tool. Not with a new order.
function sync_product_stock( $meta_id, $post_id, $meta_key, $meta_value ) {
$postType = get_post_type( $post_id );
if ($postType == 'product' ) {
if ( $meta_key == '_stock' ) {
$product = wc_get_product( $post_id );
$eventId = $product->get_attribute( 'event_id' );
$productName = $product->get_name();
if ($productName.include('Early Bird')) {
update_field( 'event_early_bird_group_event_early_bird_amount_of_tickets', $meta_value, $eventId );
} else if ($productName.include('Regular')) {
update_field( 'event_regular_group_event_regular_amount_of_tickets', $meta_value, $eventId );
} else if ($productName.include('Member')) {
// nothing needs to be updated
}
}
}
}
add_action( 'updated_post_meta', 'sync_product_stock', 10, 4);
How can I get notified when the _stock field is updated? (I don't want to handle the stock-keeping myself
There are some mistakes in your code. Try the following using woocommerce hooks:
// On processed update product stock event
add_action( 'woocommerce_updated_product_stock', 'wc_updated_product_stock_callback' );
// On admin single product creation/update
add_action( 'woocommerce_process_product_meta', 'wc_updated_product_stock_callback' );
// On admin single product variation creation/update
add_action( 'woocommerce_save_product_variation', 'wc_updated_product_stock_callback' );
function wc_updated_product_stock_callback( $product_id ) {
// get an instance of the WC_Product Object
$product = wc_get_product( $product_id );
$stock_qty = $product->get_stock_quantity();
$event_id = $product->get_attribute('event_id');
$product_name = $product->get_name();
if ( strpos($product_name, 'Early Bird') !== false ) {
update_field( 'event_early_bird_group_event_early_bird_amount_of_tickets', $stock_qty, $event_id );
} elseif ( strpos($product_name, 'Regular') !== false ) {
update_field( 'event_regular_group_event_regular_amount_of_tickets', $stock_qty, $event_id );
} elseif ( strpos($product_name, 'Member') !== false ) {
// nothing needs to be updated
}
}
Code goes in function.php file of the active child theme (or active theme). It should work.
In WooCommerce and I have added a custom field "description" for each product.
I was able to find a way to show both, the label name and the value:
add_filter( 'woocommerce_add_cart_item_data', 'save_days_field', 10, 2 );
function save_days_field( $cart_item_data, $product_id ) {
$special_item = get_post_meta( $product_id , 'description',true );
if(!empty($special_item)) {
$cart_item_data[ 'description' ] = $special_item;
// below statement make sure every add to cart action as unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'description', $special_item );
}
return $cart_item_data;
}
// Render meta on cart and checkout
add_filter( 'woocommerce_get_item_data','rendering_meta_field_on_cart_and_checkout', 10, 2 );
function rendering_meta_field_on_cart_and_checkout( $cart_item_data, $cart_item ) {
if( isset( $cart_item['description'] ) ) {
$cart_item_data[] = array( "name" => __( "Description", "woocommerce" ), "value" => $cart_item['description'] );
}
return $cart_item_data;
}
Now I need to display ONLY the value (not the label name "Description") of this custom field in the cart and checkout table. I need to display with <small>, like the attribute I am displaying with this code:
add_filter('woocommerce_cart_item_name', 'wp_woo_cart_attributes', 10, 2);
function wp_woo_cart_attributes($cart_item, $cart_item_key){
$productId = $cart_item_key['product_id'];
$product = wc_get_product($productId);
$taxonomy = 'pa_color';
$value = $product->get_attribute($taxonomy);
if ($value) {
$label = get_taxonomy($taxonomy)->labels->singular_name;
$cart_item .= "<small>$value</small>";
}
return $cart_item;
}
How can I make it for this custom field, displaying the value only?
You don't need to include a product custom field as custom cart item data, as it's directly accessible from the product object (or the product ID).
Note: On a cart item variable $cart_item, the WC_Product Object is included and available using $cart_item['data'].
Try the following to add a custom field after the item name in cart and checkout pages:
// Display in cart and checkout pages
add_filter( 'woocommerce_cart_item_name', 'customizing_cart_item_name', 10, 3 );
function customizing_cart_item_name( $product_name, $cart_item, $cart_item_key ) {
$product = $cart_item['data']; // Get the WC_Product Object
if ( $value = $product->get_meta('description') ) {
$product_name .= '<small>'.$value.'</small>';
}
return $product_name;
}
To display it on orders and email notifications use:
// Display in orders and email notifications
add_filter( 'woocommerce_order_item_name', 'customizing_order_item_name', 10, 2 );
function customizing_order_item_name( $product_name, $item ) {
$product = $item->get_product(); // Get the WC_Product Object
if ( $value = $product->get_meta('description') ) {
$product_name .= '<small>'.$value.'</small>';
}
return $product_name;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Trying to get an advanced custom field in a woocommerce product to pass to the new order email for the admin. It's only there for the admin reference and is specific to each product. I have tried and this gets it to the backend but not in the email.
add_action( 'woocommerce_before_order_itemmeta', 'product_size', 10, 3 );
function product_size( $item_id, $item, $product ){
// Only in backend Edit single Order pages
if( current_user_can('edit_shop_orders') ):
// The product ID
$product_id = $product->get_id();
// Get your ACF product value
$acf_value = __('Size: ') . get_field( 'package_size', $product_id );
// Outputing the value of the "package size" for this product item
echo '<div class="wc-order-item-custom"><strong>'. $acf_value .'</strong></div>';
endif;
}
I tried using this to get to the email but it killed the order process. It went through in the backend but after hitting place order, it just refreshes the checkout page and does not go to the thank you or generate an email.
add_action( 'woocommerce_email_order_details', 'display', 10, 4 );
function display( $order, $sent_to_admin, $plain_text, $email ) {
global $product;
$id = $product->get_id();
$value = get_field( "package_size", $id );
if($value) {
echo "<p>Package Size : ".$value ."</p>";
}
}
Any suggestions or help is appreciated.
The WC_Product object $product can't be defined as a global variable. You need to use a foreach loop to get order items first.
But as an order can have many items (products) you may get many displays for this ACF field.
Your revisited code:
add_action( 'woocommerce_email_order_details', 'display_package_size_email_order_details', 10, 4 );
function display_package_size_email_order_details( $order, $sent_to_admin, $plain_text, $email ) {
// Only admin notifications
if( ! $sent_to_admin )
return; // Exit
foreach( $order->get_items() as $item ) {
if( $package_size = get_field( "package_size", $item->get_product_id() ) ){
echo '<p><strong>'.__('Package Size').': </strong>'.$package_size.'</p>';
}
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Related: Display value from ACF field in Woocommerce order email