How to get order ID in woocommerce_email_headers hook
Updated: Added compatibility with Woocommerce version 3+
I have made some tests trying to output raw data from $order object without success. After some other tests I got now the correct order ID. I have use the code below for my test to be sure. Replace the value of $your_email
by your own email. Then you will receive an email with the order ID in the header name:
function testing_hook_headers( $headers, $id, $order ) {
// The order ID | Compatibility with WC version +3
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
$your_email = '<name@email.com>';
$headers = "To: Order Num $order_id $your_email";
return $headers;
}
add_filter( 'woocommerce_email_headers', 'testing_hook_headers', 10, 3);
So Here is your code:
function techie_custom_wooemail_headers( $headers, $email_id, $order ) {
// The order ID | Compatibility with WC version +3
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
$email = get_post_meta( $order_id, '_approver_email', true );
// Replace the emails below to your desire email
$emails = array('eee@hotmail.com', $email);
switch( $email_id ) {
case 'new_order':
$headers .= 'Bcc: ' . implode(',', $emails) . "\r\n";
break;
case 'customer_processing_order':
$headers .= 'Bcc: ' . implode(',', $emails) . "\r\n";
break;
case 'customer_completed_order':
case 'customer_invoice':
$headers .= 'Bcc: ' . implode(',', $emails) . "\r\n";
break;
default:
}
return $headers;
}
add_filter( 'woocommerce_email_headers', 'techie_custom_wooemail_headers', 10, 3);
I havent test your code as it's particular, but you have the right manner to get order ID.
Woocommerce different headers for each email types
As mentioned in the comments, I don't think there is a way to use conditional logic on the woocommerce_email_header
hook. You could go by the $header
variable, but it is kind of a long string and it could change.
First, we remove the existing email header:
function so_27400044_remove_email_header(){
remove_action( 'woocommerce_email_header', array( WC()->mailer(), 'email_header' ) );
}
add_action( 'init', 'so_27400044_remove_email_header' );
Then directly call the specific header template in your email template. For example, in the customer-invoice.php
template, we can call wc_get_template()
to directly load an appropriate/specific header. Assuming you've duplicated the email-header.php
template and renamed the one for customer invoices to email-header-invoice.php
it might look like this:
<?php
/**
* Customer invoice email
*
* @author WooThemes
* @package WooCommerce/Templates/Emails
* @version 2.2.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
?>
<?php do_action( 'woocommerce_email_header', $email_heading ); ?>
<?php wc_get_template( 'emails/email-header-invoice.php', array( 'email_heading' => $email_heading ) ) ; ?>
<?php if ( $order->has_status( 'pending' ) ) : ?>
My local set up doesn't email so I've tested it with the following:
function kia_testing(){
$order= wc_get_order( 381 );
ob_start();
wc_get_template( 'emails/customer-processing-order.php', array(
'order' => $order,
'email_heading' => 'some title',
'sent_to_admin' => false,
'plain_text' => true
) );
echo ob_get_clean();
}
add_action( 'woocommerce_before_single_product' , 'kia_testing' );
I am seeing the new header being called by the modified customer-processing-order.php
template.
WooCommerce New order email manually trigger for some products
You can put the following in your functions.php:
add_filter( 'woocommerce_email_recipient_customer_completed_order', 'your_email_recipient_filter_function', 10, 2);
function your_email_recipient_filter_function($recipient, $object) {
$recipient = $recipient . ', me@myemail.com';
return $recipient;
}
the only drawback is that the recipient will see both your address & his own in the To: field.
Alternatively, you can use the woocommerce_email_headers filter. the $object passed allows you to only apply this to the completed order email:
add_filter( 'woocommerce_email_headers', 'mycustom_headers_filter_function', 10, 2);
function mycustom_headers_filter_function( $headers, $object ) {
if ($object == 'customer_completed_order') {
$headers .= 'BCC: My name <my@email.com>' . "\r\n";
}
return $headers;
}
Taken from this answer from Ewout.
Get the customer user_id in Woocommerce email footer template
You can't get the current user in woocommerce email templates, but you can get the customer user ID from the Order.
To get the customer User ID, you can set and get some data in the $GLOBAL
variable:
- Set the data - On your active theme
function.php
file:
add_action( 'woocommerce_email_header', 'wc_email_user_id', 10, 2 );
function wc_email_user_id( $email_heading, $email ) {
// Set global variable data: user ID and Order ID
$GLOBALS['emails_custom_data'] = array(
'user_id' => get_post_meta( $email->object->ID, '_customer_user', true ), // Set the user ID
'order_id' => $email->object->ID, // Set the Order ID
);
}
- Get the data - On your template file just after:
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
## --- Your custom Code start here --- ##
$refNameGlobalsVar = $GLOBALS; // Get the data
$custom_data = $refNameGlobalsVar['emails_custom_data']; // Set the data in a variable
$user_id = $custom_data['user_id']; // Get the user ID
$order_id = $custom_data['order_id']; // Get the order ID (in case of…)
// Testing output
echo '<p>The user ID is '.$user_id.' | From the Order ID: '.$order_id.'</p>';
## --- End of custom code --- ##
?>
This code is tested and works
Different WooCommerce Email Header based on custom field value
The main error in your code is else if
which should be elseif
instead and you should rename your custom function woocommerce_email_header
differently.
There is no issue with $email->object
, which is the WC_Order
object. You can get the Order Id using $email->object->get_id()
5if needed).
Also your code can be simplified and optimized since WooCommerce 3. Try the following instead:
add_action( 'init', 'customizing_woocommerce_email_header' );
function customizing_woocommerce_email_header(){
remove_action( 'woocommerce_email_header', array( WC()->mailer(), 'email_header' ) );
add_action( 'woocommerce_email_header', 'custom_email_header', 10, 2 );
}
function custom_email_header( $email_heading, $email ) {
$template = 'email-header.php'; // Default template
if ( 'new_order' === $email->id && 'delivery' === $email->object->get_meta( 'delivery_type' ) ) {
$template = 'email-header-alt.php'; // Custom template
}
wc_get_template( 'emails/'.$template, array( 'email_heading' => $email_heading ) );
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Targeting specific email with the email id in Woocommerce
The wc_order_email
class or function doesn't exist in WooCommerce, so I have updated your question.
What you are looking at is $email
variable argument (the WC_Email
current type object). It's mostly defined everywhere in templates and hooks.
To get the usable current Email ID as a variable you will simply use $email_id = $email->id
…
To get the current Email ID of your custom emails, you should use this code (just for testing):
add_action( 'woocommerce_email_order_details', 'get_the_wc_email_id', 9, 4 );
function get_the_wc_email_id( $order, $sent_to_admin, $plain_text, $email ) {
// Will output the email id for the current notification
echo '<pre>'; print_r($email->id); echo '</pre>';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
You will get the following:
new_order
customer_on_hold_order
customer_processing_order
customer_completed_order
customer_refunded_order
customer_partially_refunded_order
cancelled_order
failed_order
customer_reset_password
customer_invoice
customer_new_account
customer_note
Once you get the correct email ID slug for your custom email notification you can use it on any following hook (instead of overriding email templates):
• woocommerce_email_header
(2 arguments: $email_heading
, $email
)
• woocommerce_email_order_details
(4 arguments: $order
, $sent_to_admin
, $plain_text
, $email
)
• woocommerce_email_order_meta
(4 arguments: $order
, $sent_to_admin
, $plain_text
, $email
)
• woocommerce_email_customer_details
(4 arguments: $order
, $sent_to_admin
, $plain_text
, $email
)
• woocommerce_email_footer
(1 argument: $email
)
HERE an example of code where I target "New order" email notifications only:
add_action( 'woocommerce_email_order_details', 'add_custom_text_to_new_order_email', 10, 4 );
function add_custom_text_to_new_order_email( $order, $sent_to_admin, $plain_text, $email ) {
// Only for "New Order" email notifications (to be replaced by yours)
if( ! ( 'new_order' == $email->id ) ) return;
// Display a custom text (for example)
echo '<p>'.__('My custom text').'</p>';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works.
Output product custom field in woocommerce email header
Just replace your code with follows code snippet -
add_action('woocommerce_email_header', 'wcv_ingredients_email_logo', 10, 2);
function wcv_ingredients_email_logo( $email_heading, $email ){
if($email->object){
foreach($email->object->get_items() as $item_values){
// Get the product ID for simple products (not variable ones)
$product = $item_values->get_product();
$image_id = get_post_meta( $product->get_id(), 'store_email_logo', true ); //get the image ID associated to the product
$image_src = wp_get_attachment_image_src( $image_id, 'full' )[0]; //get the src of the image - you can use 'full', 'large', 'medium', or 'thumbnail' here,
$image = '<img src="'.$image_src.'">'; //create the img element
echo $image . '<br>'; //echo the image
}
}
}
Related Topics
How to Detect If a User Has Logged Out, in PHP
Getting Elements of a Div from Another Page (Php)
Replace the Last Comma in a String Using Regular Expression
Select Statement with Fetch_Array in MySQLi Prepared Statements
PHP - Hide Url (Get) Parameters
How to Determine If a PHP File Is Loaded via Cron/Command Line
Clear Data in MySQL Table with PHP
Soapclient: How to Pass Multiple Elements with Same Name
Error 1366 (Hy000): Incorrect String Value: '\Xf0\X9F\X98\X9C' for Column 'Comment' at Row 1
Linkify Regex Function PHP Daring Fireball Method
Woocommerce: Display Also Product Variation Description on Cart Items
Php: Check If Xml Node Exists with Attribute
How to Remove Values from an Array in PHP
PHP $String{0} VS. $String[0];
Output (Echo/Print) Everything from a PHP Array