I hope it's a dumb question, but I can't find a smart solution at the moment.
I've got a custom field in my products page - which is a Relationship field - and I'd like to display a field of my RF for every product in my cart page.
More specifically: I have a product associated with a brand. The brand has a 'shipping time' field.
At the moment my function is partially working, in the sense that it displays the request value, but ONLY for the first item in the cart.
That's my code in function.php
add_filter( 'woocommerce_get_item_data', 'wc_add_shipping_to_cart', 10, 2 );
function wc_add_shipping_to_cart( $cart_data, $cart_item )
{
$custom_shipping = array();
if( !empty( $cart_data ) )
$custom_shipping = $cart_data;
// Get the product ID
$product_id = $cart_item['product_id'];
$custom_field_value = get_post_meta( $product_id, 'brand_select', true );
$display_brand_shipping = get_field('shipping_time_brand', $custom_field_value);
if( $custom_field_value = get_post_meta( $product_id, 'brand_select', true ) )
$custom_shipping[] = array(
'name' => __( 'Shipping', 'woocommerce' ),
'value' => $display_brand_shipping,
'display' => $display_brand_shipping,
);
return $custom_shipping; }
Could you help me?
Your code is not testable as is not possible to reproduce your issue related to product custom field and ACF fields, but it can be simplified this way:
add_filter( 'woocommerce_get_item_data', 'wc_add_shipping_to_cart', 10, 2 );
function wc_add_shipping_to_cart( $cart_item_data, $cart_item )
{
if( $brand_select = get_post_meta( $cart_item['product_id'], 'brand_select', true ) ) {
if( $shipping_time = get_field('shipping_time_brand', $brand_select ) ) {
$cart_item_data[] = array(
'name' => __( 'Shipping', 'woocommerce' ),
'value' => $shipping_time,
);
}
}
return $cart_item_data;
}
Code goes in function.php file of your active child theme (or active theme).
Related
I have created a custom field in WooCommerce product variations. I was able to store information in this field for each specific variation. The code I used is the following and it works:
add_action( 'woocommerce_variation_options_pricing', 'upf_add_custom_field_to_variations', 10, 3 );
function upf_add_custom_field_to_variations( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input( array(
'id' => 'custom_field[' . $loop . ']',
'class' => 'short',
'label' => __( 'Custom:', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, 'custom_field', true )
) );
}
// -----------------------------------------
add_action( 'woocommerce_save_product_variation', 'upf_save_custom_field_variations', 10, 2 );
function upf_save_custom_field_variations( $variation_id, $i ) {
$custom_field = $_POST['custom_field'][$i];
if ( isset( $custom_field ) ) update_post_meta( $variation_id, 'custom_field', esc_attr( $custom_field ) );
}
// -----------------------------------------
add_filter( 'woocommerce_available_variation', 'upf_add_custom_field_variation_data' );
function upf_add_custom_field_variation_data( $variations ) {
$variations['custom_field'] = '<div class="woocommerce_custom_field">Custom: <span>' . get_post_meta( $variations[ 'variation_id' ], 'custom_field', true ) . '</span></div>';
return $variations;
}
Now I want to create a short code to get the field name and value. If I create this shortcode I will be able to use this field in a custom page which is my goal. I tried different options but couldn't find a way. Could you please help me to complete my code. Thank you!
I'm making a shop page that's showing every variation of the product as single products. Using this plugin to achieve that. And I need the variation description to show up, too. However, I have no idea how to achieve this. I know there's a woocommerce_template_single_excerpt function, but that shows Attribute information, instead. So, this:
add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_single_excerpt', 20 );
Gives back Attributes titles (i.e. Size, Color). But is there any way I can pull out the description that's stored in every single variation inside the product?
Thanks a bunch in advance!
I found a workaround, in a way, for anyone who runs into the same issue.
Because I had no idea how to access variation description, I created a new field called Shop Description:
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
add_filter( 'woocommerce_available_variation', 'load_variation_settings_fields' );
function variation_settings_fields( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input(
array(
'id' => "shop_description{$loop}",
'name' => "shop_description[{$loop}]",
'value' => get_post_meta( $variation->ID, 'shop_description', true ),
'label' => __( 'Shop Description', 'woocommerce' ),
'desc_tip' => true,
'description' => __( 'Shop description.', 'woocommerce' ),
'wrapper_class' => 'form-row form-row-full',
)
);
}
function save_variation_settings_fields( $variation_id, $loop ) {
$text_field = $_POST['shop_description'][ $loop ];
if ( ! empty( $text_field ) ) {
update_post_meta( $variation_id, 'shop_description', esc_attr( $text_field ));
}
}
function load_variation_settings_fields( $variation ) {
$variation['shop_description'] = get_post_meta( $variation[ 'variation_id' ], 'shop_description', true );
return $variation;
}
After that, I used a custom function and add_action to show it on the Shop/Archive page. You'll have to play around with the priority, as that's not sorted out here.
add_action( 'woocommerce_after_shop_loop_item_title', 'show_woocommerce_product_excerpt', 35 );
function show_woocommerce_product_excerpt() {
global $post;
if ( is_home() || is_shop() || is_product_category() || is_product_tag() ) {
echo '<p class="excerpt">';
echo get_post_meta( $post->ID, 'shop_description', true );
echo '</p>';
}
}
And then, just add a description for each variation in your Products and it'll show up on Shop page without any issues.
as I am trying to add one extra data so that I can fetch and filter the data according to the meta after successfull payment. Let me explain using code.
$cart_data = array(
'product_id' => $product_id,
'payment_type' => 'subscription',
'**what_is_being_promoted**' => $promoting,
);
WC()->cart->add_to_cart($product_id, 1, null, null, $cart_item_data);
now i would like to read the key 'what_is_being_promoted' in classifier_update_user_data_upon_payment hook.
how to achieve that.
You can use below filters/action to add additional data to cart item:
//Add custom cart item data
function zwtadd_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
if( isset( $_POST['what_is_being_promoted'] ) ) {
$cart_item_data['zwt_field'] = sanitize_text_field( $_POST['what_is_being_promoted'] );
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'zwtadd_cart_item_data', 10, 3 );
//Display custom item data in the cart
function zwt_get_item_data( $item_data, $cart_item_data ) {
if( isset( $cart_item_data['zwt_field'] ) ) {
$item_data[] = array(
'key' => __( 'Is promoted', 'text-domain' ),
'value' => wc_clean( $cart_item_data['zwt_field'] )
);
}
return $item_data;
}
add_filter( 'woocommerce_get_item_data', 'zwt_get_item_data', 10, 2 );
//Add custom meta to order
function zwt_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
if( isset( $values['zwt_field'] ) ) {
$item->add_meta_data(__( 'Is promoted', 'text-domain' ), $values['zwt_field'], true);
}
}
add_action( 'woocommerce_checkout_create_order_line_item', 'zwt_checkout_create_order_line_item', 10, 4 );
Above code will add data to cart item, display data to cart and same will display in the order.
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;
}
I am using woocommerce on my wordpress site.
I am selling paintings. The products are paintings.
I have a list of artists as posts. Each artist is one post.
I would like to connect the posts and products so I can show the artist's name on the painting page and the user can click on the name and it takes them to the artist post.
How do I do this?
This is an example of how to add a custom field in WooCommerce product general tab. Since artists are posts ( category is not specified ), it will collect links for all posts and place them in a dropdown. The value of this field will be visible on the single product page below the price ( you can open the content-single-product.php file in WooCommerce theme, to see the actions for single product template, and functions attached, and change the priority of woocommerce_product_artist function if you want to change the place where the link will appear ).
<?php
add_action( 'admin_init', 'woocommerce_custom_admin_init' );
function woocommerce_custom_admin_init() {
// display fields
add_action( 'woocommerce_product_options_general_product_data', 'woocommerce_add_custom_general_fields' );
// save fields
add_action( 'woocommerce_process_product_meta', 'woocommerce_save_custom_general_fields' );
}
function woocommerce_add_custom_general_fields() {
// creating post array for the options ( id => title)
$posts = array( '' => __( 'Select Artist' ) );
array_walk( get_posts( array( 'numberposts' => -1 ) ), function( $item ) use ( &$posts ) {
$posts[ $item->ID ] = $item->post_title;
} );
// creating dropdown ( woocommerce will sanitize all values )
echo '<div class="options_group">';
woocommerce_wp_select(
array(
'id' => '_artist',
'label' => __( 'Artist' ),
'options' => $posts
)
);
echo '</div>';
}
function woocommerce_save_custom_general_fields( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
// validate id of artist page and save
if ( isset( $_POST['_artist'] ) ) {
$value = filter_input( INPUT_POST, '_artist', FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 0 ) ) );
update_post_meta( $post_id, '_artist', $value );
}
}
add_action( 'init', 'woocommerce_custom_init' );
function woocommerce_custom_init() {
// hook the woocommerce_product_artist function on to woocommerce_single_product_summary action ( priority 15 )
add_action( 'woocommerce_single_product_summary', 'woocommerce_product_artist', 15 );
}
function woocommerce_product_artist() {
global $post;
// get the artist page id and show in template ( if exists )
$artist_id = get_post_meta( $post->ID, '_artist', true );
if ( $artist_id ) :
?>
<div class="product-artist"><?php echo get_the_title( $artist_id ); ?></div>
<?php endif;
}
?>