Display specific product attribute in WooCommerce email notifications - php

I can't manage to add a product attribute to a WooCommerce new order email. I have added the snippet below to email-order-items.php (after // SKU.. part), but nothing happens. Even the titel 'Location:' isn't visible. Any thoughts on this?
// Attribute
if ( $item_meta->meta ) {echo '<br/><small>Location: ' . nl2br( $product->get_attribute( 'location' ) ) . '</small>';}

Updated - Instead of overriding Woocommerce templates, always try first to use available hooks like:
add_action( 'woocommerce_order_item_meta_start', 'add_download_links_to_thank_you_page', 10, 3 );
function add_download_links_to_thank_you_page( $item_id, $item, $order ) {
// Set below your product attribute taxonomy (always starts with "pa_")
$taxonomy = 'pa_location';
// On email notifications
if ( ! is_wc_endpoint_url() && $item->is_type('line_item') ) {
$product = $item->get_product();
$label_name = get_taxonomy( $taxonomy )->labels->singular_name;
if ( $term_names = $product->get_attribute( $taxonomy ) ) {
echo '<br/><small>' . $label_name . ': ' . nl2br( $term_names ) . '</small>';
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
You can also use woocommerce_order_item_meta_end hook instead.

Related

How to show WooCommerce custom product meta in new order emails?

I'm currently successfully saving custom post meta for a single product as follows:
function save_payment_terms( $product_id ) {
if ( isset( $_POST['payment_terms'] ) ) {
update_post_meta( $product_id, 'payment_terms', is_numeric( $_POST['payment_terms'] ) ? absint( wp_unslash( $_POST['payment_terms'] ) ) : '1' );
}
}
How would I go about adding that custom post meta to a new order confirmation email? I've tried the following hooks without success: woocommerce_email_order_meta and woocommerce_order_item_meta_start. The latest iteration looking as follows:
add_action('woocommerce_order_item_meta_start', 'email_confirmation_display_order_items', 10, 4);
function email_confirmation_display_order_items($item_id, $item, $order, $plain_text) {
echo '<div>Terms: '. wc_get_order_item_meta( $item_id, 'payment_terms') .'</div>';
}
Resulting in:
Doing a var_dump of wc_get_order_item_meta, I get: ../snippet-ops.php(446) : eval()'d code:7:boolean false
Anyone that could shed some light on this?
Try the following instead:
add_action( 'woocommerce_order_item_meta_start', 'email_confirmation_display_order_items', 10, 3 );
function email_confirmation_display_order_items( $item_id, $item, $order ) {
// On email notifications for line items
if ( ! is_wc_endpoint_url() && $item->is_type('line_item') ) {
$payment_terms = get_post_meta( $item->get_product_id(), 'payment_terms', true );
if ( ! empty($payment_terms) ) {
printf( '<div>' . __("Terms: %s", "woocommerce") . '</div>', $payment_terms );
}
}
}
Code goes in functions.php file of your active child theme (or active theme). It should works.
Related: WooCommerce Display avanced custom fields (ACF) inside order notification

Woocommerce - How to display the price in the ADD-TO-CART button? [duplicate]

Been trying to find something about this, but the solutions I found so far here do not work.
I need, in the single product page, to display the add to cart button like this:
ADD TO CART - JUST $PRICE
It needs to be done from the functions.php file in the child theme.
Thanks a lot!
To handle the display of the product price in add-to-cart button for all product prices on shop, other archives pages and single product pages, without any need of overriding templates, using dedicated Woocommerce filter hooks:
add_filter( 'woocommerce_product_add_to_cart_text', 'custom_add_to_cart_price', 20, 2 ); // Shop and other archives pages
add_filter( 'woocommerce_product_single_add_to_cart_text', 'custom_add_to_cart_price', 20, 2 ); // Single product pages
function custom_add_to_cart_price( $button_text, $product ) {
// Variable products
if( $product->is_type('variable') ) {
// shop and archives
if( ! is_product() ){
$product_price = wc_price( wc_get_price_to_display( $product, array( 'price' => $product->get_variation_price() ) ) );
return $button_text . ' - From ' . strip_tags( $product_price );
}
// Single product pages
else {
return $button_text;
}
}
// All other product types
else {
$product_price = wc_price( wc_get_price_to_display( $product ) );
return $button_text . ' - Just ' . strip_tags( $product_price );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
On shop page:
On single product pages:
I would suggest you override the WooCommerce template from the child theme, the file name is add-to-cart.php and can be found at woocommerce > loop.
At the bottom add the following code, it will be displayed only in product single.
if (is_single()) {
echo sprintf(
'<span>%s %s</span>',
esc_attr__('JUST', 'woocommerce'),
esc_attr($product->price)
);
}
Edit your woocommerce/loop/add-to-cart.php template file like this:
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product;
echo apply_filters( 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
sprintf( '<a href="%s" data-quantity="%s" class="%s" %s>ADD TO CART - JUST %s</a>',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 ),
esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
$product->get_price()
),
$product, $args );
For the single product pages do basically the same in:
woocommerce/single-product/add-to-cart/simple.php
And any other template you use in the add-to-cart directory.
Note: Don't edit the plugin file itself but override the template in your (child) theme so it won't be overwritten when the plugin gets updated.

Display price on add to cart button from the functions.php file in Woocommerce

Been trying to find something about this, but the solutions I found so far here do not work.
I need, in the single product page, to display the add to cart button like this:
ADD TO CART - JUST $PRICE
It needs to be done from the functions.php file in the child theme.
Thanks a lot!
To handle the display of the product price in add-to-cart button for all product prices on shop, other archives pages and single product pages, without any need of overriding templates, using dedicated Woocommerce filter hooks:
add_filter( 'woocommerce_product_add_to_cart_text', 'custom_add_to_cart_price', 20, 2 ); // Shop and other archives pages
add_filter( 'woocommerce_product_single_add_to_cart_text', 'custom_add_to_cart_price', 20, 2 ); // Single product pages
function custom_add_to_cart_price( $button_text, $product ) {
// Variable products
if( $product->is_type('variable') ) {
// shop and archives
if( ! is_product() ){
$product_price = wc_price( wc_get_price_to_display( $product, array( 'price' => $product->get_variation_price() ) ) );
return $button_text . ' - From ' . strip_tags( $product_price );
}
// Single product pages
else {
return $button_text;
}
}
// All other product types
else {
$product_price = wc_price( wc_get_price_to_display( $product ) );
return $button_text . ' - Just ' . strip_tags( $product_price );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
On shop page:
On single product pages:
I would suggest you override the WooCommerce template from the child theme, the file name is add-to-cart.php and can be found at woocommerce > loop.
At the bottom add the following code, it will be displayed only in product single.
if (is_single()) {
echo sprintf(
'<span>%s %s</span>',
esc_attr__('JUST', 'woocommerce'),
esc_attr($product->price)
);
}
Edit your woocommerce/loop/add-to-cart.php template file like this:
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product;
echo apply_filters( 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
sprintf( '<a href="%s" data-quantity="%s" class="%s" %s>ADD TO CART - JUST %s</a>',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 ),
esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' ),
isset( $args['attributes'] ) ? wc_implode_html_attributes( $args['attributes'] ) : '',
$product->get_price()
),
$product, $args );
For the single product pages do basically the same in:
woocommerce/single-product/add-to-cart/simple.php
And any other template you use in the add-to-cart directory.
Note: Don't edit the plugin file itself but override the template in your (child) theme so it won't be overwritten when the plugin gets updated.

Customize order item meta only for WooCommerce admin email notifications

I need to add custom taxonomy to admin new order emails but not to customer emails. My current code displays my custom taxonomy for each item in the order but it is showing up in both admin and customer emails, which I don't want.
Looking thru email-order-items.php I don't see a way to utilize $sent_to_admin in the hook that I am using. Am I missing something?
How do I add my custom taxonomy only to admin emails using just hooks and filters?
add_action( 'woocommerce_order_item_meta_end', 'custom_woocommerce_order_item_meta_end', 10, 3 );
function custom_woocommerce_order_item_meta_end( $item_id, $item, $order ) {
$product = $item->get_product();
$locations = get_the_terms( $product->get_id(), 'my_custom_taxonomy' );
echo '<br/>';
echo '<div style="margin-top: 20px;">';
foreach( $locations as $location ) {
echo 'Location: <b>' . $location->name . '</b>';
echo '<br/>';
}
echo '</div>
}
This can be done using $GLOBAL variable. I have revisited a bit your code too. Try this:
// Setting the "sent_to_admin" as a global variable
add_action('woocommerce_email_before_order_table', 'email_order_id_as_a_global', 1, 4);
function email_order_id_as_a_global($order, $sent_to_admin, $plain_text, $email){
$GLOBALS['email_data'] = array(
'sent_to_admin' => $sent_to_admin, // <== HERE we set "$sent_to_admin" value
'email_id' => $email->id, // The email ID (to target specific email notification)
);
}
// Conditionally customizing footer email text
add_action( 'woocommerce_order_item_meta_end', 'custom_email_order_item_meta_end', 10, 3 );
function custom_email_order_item_meta_end( $item_id, $item, $order ){
// Getting the custom 'email_data' global variable
$refNameGlobalsVar = $GLOBALS;
$email_data = $refNameGlobalsVar['email_data'];
// Only for admin email notifications
if( ! ( is_array( $email_data ) && $email_data['sent_to_admin'] ) ) return;
## -------------------------- Your Code below -------------------------- ##
$taxonomy = 'my_custom_taxonomy'; // <= Your custom taxonomy
echo '<br/><div style="margin-top: 20px;">';
foreach( get_the_terms( $item->get_product_id(), $taxonomy ) as $term )
echo 'Location: <b>' . $term->name . '</b><br/>';
echo '</div>';
}
Code goes in function.php file of the active child theme (or active theme).
Tested and works.

Advanced Custom Fields in WooCommerce Email templates

I am using Advanced Custom Fields (ACF) plugin in WooCommerce and I have set a custom field named "tracking-no".
How can I display the value of this custom field in the Woocommerce template emails/customer-completed-order.php?
I am using this code:
<?php
if(get_field('tracking-no'))
{
echo '<p>' . get_field('tracking-no') . '</p>';
}
?>
But I doesn't get anything.
Thanks
In your WooCommerce template you should get first the order ID as argument in get_field():
<?php
// Get the $order ID (WooCommerce version compatibility)
if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
$order_id = int_val( $order->id ); // Older than 3.0
} else {
$order_id = int_val( $order->get_id() ); // 3.0+
}
$tracking_num = get_field('tracking-no', $order_id );
if( $tracking_num ){
echo '<p>' . $tracking_num . '</p>';
}
?>
You can also use instead any email notification hook that you can find on this template, this way:
add_action( 'woocommerce_email_order_details', 'my_custom_field_in_completed_notification', 10, 4 );
function my_custom_field_in_completed_notification( $order, $sent_to_admin, $plain_text, $email ){
// Get the $order ID (WooCommerce version compatibility)
if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
$order_id = int_val( $order->id ); // Older than 3.0
} else {
$order_id = int_val( $order->get_id() ); // 3.0+
}
$tracking_num = get_field('tracking-no', $order_id );
if( $tracking_num ){
echo '<p>' . $tracking_num . '</p>';
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
In this case we don't override WooCommerce templates. You can also use that 2 similar hooks:
woocommerce_email_order_meta
woocommerce_email_customer_details

Categories