How to get a billing custom field from WooCommerce orders [duplicate] - php

This question already has answers here:
How to get WooCommerce order details
(6 answers)
Closed 2 years ago.
How can I get a custom billing field from my WooCommerce order? For example I've WooCommerce Germanized installed which adds a custom billing field named vat_id.
I've found a function get_address_prop() in the WooCommerce orders class but this function is protected so I can't call it with $order->get_address_prop().
Any ideas? Thanks!

This is my function I've created to retrieve any custom billing field I want:
/**
* Returns a custom billing field value
*
* #param object $order
* #param string $custom_field
*
* #return string
*/
function get_custom_billing_field( object $order, string $custom_field ): string {
$order_data = $order->get_data();
$custom_field_val = '';
if ( ! empty( $order_data ) && isset( $order_data['billing'][ $custom_field ] ) ) {
$custom_field_val = $order_data['billing'][ $custom_field ];
}
return apply_filters( 'get_custom_billing_field', $custom_field_val );
}
This is an example call for retrieving the vat_id set in WooCommerce Germanized Pro:
$order = wc_get_order( 22 );
get_custom_billing_field( $order, 'vat_id' );
I hope this helps someone. If you got a better idea, please let me know.

Related

How to remove certain meta data from customer emails (Woocommerce)?

I have products that have a non-required field to upload a file.
After checkout, both admin and customer get an email about the order.
If an item has a file "attached" to it, the mail includes a preview image and a link to the file on my shop server. I would like to remove these two but not the filename from the customer's email. As far as I have seen, there is a hook to add things to what is being shown in mails. But how can I remove data?
add_action( 'woocommerce_order_item_meta_start', 'action_woocommerce_order_item_meta_start', 10 , 4 );
function action_woocommerce_order_item_meta_start( $item_id, $item, $order, $plain_text ) {
// only email notifications
if ( is_wc_endpoint_url() ) return;
$metadata = $item['item_meta'];
// ???
}
The part of the mail looks like this:
Solution:
add_filter( 'woocommerce_order_item_display_meta_value', 'change_order_item_meta_value', 20, 3 );
/**
* Changing a meta value
* #param string $value The meta value
* #param WC_Meta_Data $meta The meta object
* #param WC_Order_Item $item The order item object
* #return string The title
*/
function change_order_item_meta_value( $value, $meta, $item ) {
// only email notifications
if ( is_wc_endpoint_url() ) return;
// By using $meta-key we are sure we have the correct one.
if (strstr($meta->key, "Druckvorlage")) {
$value = strip_tags($value);
}
return $value;
}
Here is a good post on working with order item meta data: https://www.ibenic.com/manage-order-item-meta-woocommerce/

Using WC_Tax::get_tax_classes() to get all WooCommerce tax-classes

I try to get the active tax-classes in Woocommerce in my custom plugin. When I use the WC_Tax::get_tax_classes(), I get a empty array.
How does WC_tax class work without order details and run by itself?
WC_Tax::get_tax_classes() returns an empty array when there is only the default tax class set in WooCommerce > Tax (tab) settings.
It's used for example in wc_get_product_tax_class_options() function that displays the available tax classes in admin product pages settings:
/**
* Get product tax class options.
*
* #since 3.0.0
* #return array
*/
function wc_get_product_tax_class_options() {
$tax_classes = WC_Tax::get_tax_classes();
$tax_class_options = array();
$tax_class_options[''] = __( 'Standard', 'woocommerce' );
if ( ! empty( $tax_classes ) ) {
foreach ( $tax_classes as $class ) {
$tax_class_options[ sanitize_title( $class ) ] = $class;
}
}
return $tax_class_options;
}
So the default tax class (active tax class) has no entry when using WC_Tax::get_tax_classes().
Then you can use wc_get_product_tax_class_options() function to get all WooCommerce tax classes or the code from this function if you want something more custom.
Related: How to get the available tax rates in WooCommerce

Get meta data via "woocommerce_order_get_formatted_billing_address" filter hook

Im trying to apply a custom post meta field billing_company_id to orders formatterd billing address, and place it below billing company.
Via the following code I can apply a string but how to get the custom post meta from an order?
add_action( 'woocommerce_order_get_formatted_billing_address', 'company_billing_id', 20, 1 );
function company_billing_id($address){
$address .= 'Custom field string';
return $address;
}
The woocommerce_order_get_formatted_billing_address filter hook contains not 1 but 3 parameters.
Via the 3rd you have access to the $order object, so you could use something like:
/**
* Filter orders formatterd billing address.
*
* #since 3.8.0
* #param string $address Formatted billing address string.
* #param array $raw_address Raw billing address.
* #param WC_Order $order Order data. #since 3.9.0
*/
function filter_woocommerce_order_get_formatted_billing_address( $address, $raw_address, $order ) {
// Get meta
$value = $order->get_meta( 'billing_company_id' );
// NOT empty
if ( ! empty ( $value ) ) {
// Append
$address .= $value;
}
return $address;
}
add_filter( 'woocommerce_order_get_formatted_billing_address', 'filter_woocommerce_order_get_formatted_billing_address', 10, 3 );

About update product stock status function in WooCommerce 3

The deal is, I have to fix an error in a custom WooCommerce import plugin, which appeared after updating WC from 2.6 to 3.4.
It uses the 'wc_update_product_stock_status' function, and used to pass post (product) id and it's stock status as it is represented in DB ('instock' and 'outofstock', as a string). But nowadays, as I can see in the WooCommerce docs (https://docs.woocommerce.com/wc-apidocs/function-wc_update_product_stock_status.html) it accepts integer instead of string.
So, the question is - what are those integers for in/out of stock values (1/0 did not fit).
If you look to the source code in wc_update_product_stock_status() function:
/**
* Update a product's stock status.
*
* #param int $product_id
* #param int $status
*/
function wc_update_product_stock_status( $product_id, $status ) {
$product = wc_get_product( $product_id );
if ( $product ) {
$product->set_stock_status( $status );
$product->save();
}
}
It uses the WC_Product set_stock_status() Woocommerce 3 CRUD method which uses strings But not integers values:
/**
* Set stock status.
*
* #param string $status New status.
*/
public function set_stock_status( $status = 'instock' ) {
$valid_statuses = wc_get_product_stock_status_options();
if ( isset( $valid_statuses[ $status ] ) ) {
$this->set_prop( 'stock_status', $status );
} else {
$this->set_prop( 'stock_status', 'instock' );
}
}
So it's an error in the comment usage in wc_update_product_stock_status() function.
It still uses: 'instock' and 'outofstock' status strings. the default value is 'instock'…
The main difference is also that stock status is now handled as outofstock term for the custom taxonomy product_visibility
Before Woocommerce 3, stock status was handled as product meta data.

Woocommerce: Which hook to replace deprecated "woocommerce_add_order_item_meta"

Need to add custom meta to order items. Googled it and most articles says to use "woocommerce_add_order_item_meta" hook. This hook is deprecated in the newest version 2.3.7. Someone, please tell me which hook to use instead.
http://docs.woothemes.com/wc-apidocs/function-woocommerce_add_order_item_meta.html
2017/2018 THE RIGHT WAY (Using new CRUD setters and Getters methods)
Related: Replace woocommerce_add_order_item_meta hook in Woocommerce 3.4
Since woocommerce 3 that has improved many things making drastic changes, the action hook woocommerce_add_order_item_meta still work perfectly even in woocommerce version 3.3+.
This hook is enabled by WC_Checkout class methods and related functions in the checkout process and not in WC_Order Class where cart data is not anymore available.
Now as Woocommmerce 3 has introduced new CRUD setters and getters methods, the similar replacement hook to be used is woocommerce_checkout_create_order_line_item that has similar useful arguments as cart data.
The woocommerce_new_order_item is really NOT convenient as cart data is not accessible.
Let see how to work with woocommerce_checkout_create_order_line_item. It has 4 available arguments:
$item is an instance of WC_Order_Item_Product new introduced Class
$cart_item_key is the cart item unique hash key
$values is the cart item
$order an instance of the WC_Order object (This is a very useful additional argument in some specific cases)
In this hook we will replace the old working functions wc_add_order_item_meta() by the new WC_Data update_meta_data() method to be used with $item argument.
Example:
## --- New way --- ##
add_action( 'woocommerce_checkout_create_order_line_item', 'custom_checkout_create_order_line_item', 20, 4 );
function custom_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
// Get a product custom field value
$custom_field_value = get_post_meta( $item->get_product_id(), '_meta_key', true );
// Update order item meta
if ( ! empty( $custom_field_value ) ){
$item->update_meta_data( 'meta_key1', $custom_field_value );
}
// … … Or … …
// Get cart item custom data and update order item meta
if( isset( $values['custom_data'] ) ) {
$item->update_meta_data( 'meta_key2', $values['custom_data'] );
}
}
Finally we can do the same with old way using woocommerce_add_order_item_meta hook as it has nearly the same useful arguments:
## --- Old way --- ##
add_action( 'woocommerce_add_order_item_meta', 'custom_add_order_item_meta', 20, 3 );
function custom_add_order_item_meta( $item_id, $values, $cart_item_key ) {
// Get a product custom field value
$custom_field_value = get_post_meta( $values['data']->get_id(), '_meta_key', true );
// Update order item meta
if ( ! empty( $custom_field_value ) ){
wc_add_order_item_meta( $item_id, 'meta_key1', $custom_field_value );
}
// … … Or … …
// Get cart item custom data and update order item meta
if( isset( $values['custom_data'] ) ) {
wc_add_order_item_meta( $item_id, 'meta_key2', $values['custom_data'] );
}
}
Conclusion: woocommerce_checkout_create_order_line_item is the right replacement hook to be used with WooCommerce 3+ and that new CRUD setters and getters methods.
If you look at wc-deprecated-functions.php you will see
/**
* #deprecated
*/
function woocommerce_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) {
return wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique );
}
Basically, the function was renamed to wc_add_order_item_meta(), so if you need the function then use that. The action hook was not renamed and remains in class-wc-checkout.php as:
// Allow plugins to add order item meta
do_action( 'woocommerce_add_order_item_meta', $item_id, $values, $cart_item_key );
It seems that the hook is now also deprecated as of version 3.0.4.
I'm getting this notification:
The The "woocommerce_add_order_item_meta" hook uses out of date data structures and function is deprecated since version 3.0.4. Replace with woocommerce_new_order_item.
I have replaced the action name 'woocommerce_add_order_item_meta' with 'woocommerce_new_order_item' in an add_action statement in an offending plugin, and the deprecation notification disappears, The problem is that some parameters now appear inside a legacy_values array. I use the plugin YITH WooCommerce Product Add Ons, and the product meta data that should be attached to an order is not picked up by the plugin and therefore not stored with the order. So until this is fixed in the plugin you have to live with the deprecation notification.
I know this has been answered and there is an accepted reply already. I just wanted to give another way to handle this without actually getting a deprecated message (see reference);
add_action('woocommerce_new_order_item', 'saveMetaData', 10, 3); // or use just 2 instead of 3; if you don't need order id
/**
* Add meta to order item
*
* #param int $itemId
* #param WC_Order_Item_Product|WC_Order_Item_Shipping $item
* #param int #orderId
*/
function saveMetaData($itemId, $item, $orderId)
{
if (!isItemValid($item))
{
return;
}
wc_add_order_item_meta($itemId, 'my_custom_data', $item->legacy_values['my_custom_data']);
}
/**
* #param WC_Order_Item_Product|WC_Order_Item_Shipping $item
*
* #return bool
*/
function isItemValid($item)
{
return (
$item instanceof WC_Order_Item_Product &&
isset($item->legacy_values) &&
isset($item->legacy_values['my_custom_data']) &&
!empty($item->legacy_values['my_custom_data'])
);
}
Your specific use case isn't very clear (you didn't specify when or where you need to add this meta info), but you can use woocommerce_checkout_update_order_meta during checkout.
Read more in customizing checkout fields.
No it seems like the hook is also deprecated:
PHP Error:
The "woocommerce_add_order_item_meta" hook uses out of date data structures and function is deprecated since version 3.1.2. Replace with woocommerce_new_order_item.
I also cannot find it here:
https://docs.woocommerce.com/wc-apidocs/hook-docs.html
I wanted to add on to Ilgıt Yıldırım's answer: in my case, my custom values did not exist in the item->legacy_values array. To fix this, I used the woocommerce_checkout_create_order_line_item hook to add the custom values to the item prior to calling the woocommerce_new_order_item hook. Here is an example of that:
add_action( 'woocommerce_checkout_create_order_line_item', 'save_values_in_item', PHP_INT_MAX, 4 );
function save_values_in_item( $item, $cart_item_key, $values, $order ) {
$item->myCustomValues = $values;
}
//THEN call the new hook:
add_action( 'woocommerce_new_order_item', 'add_product_input_fields_to_order_item_meta_wc3', PHP_INT_MAX, 3 );
function add_product_input_fields_to_order_item_meta_wc3( $item_id, $item, $order_id ) {
if ( isset( $item->myCustomValues ) )
{
//iterate through array and place desired values into the meta data using the wc_add_order_item_meta function
}
}
Just to make things clear, this function was deprecated, but the hook is still ok

Categories