WC_Order items empty - wordpress

this is very strange, i am calling $order = new WC_Order(52); and I get a correct order object but the Items array is empty.
Any ideas whats going wrong ?
I am using WooCommerce 3.4.3.

I also thought what you are doing should work but in fact it is wrong. I read the WooCommerce source code and this is how WooCommerce does it.
if ( ! $order = wc_get_order( $order_id ) ) {
return;
}
$order_items = $order->get_items( apply_filters( 'woocommerce_purchase_order_item_types', 'line_item' ) );
The $order->get_items() call will check if the line item has been read from the data store and read it if it has not yet been read. So, new WC_Order(52) actually only partially initializes the order object. The order items are initialized later when they are accessed through the order. This may be more efficient as items that are not used will not be initialized. Please note that the order is created by using the wc_get_order() function. You should do this instead of new WC_Order() as this uses the factory to create the order.

The solution provided here is correct. However if you are trying to get the order items on woocommerce_new_order it will not solve your problem since line items are assigned to the order after the woocommerce_new_order hook is triggered.
I only managed to sort my issues after I changed the hook to woocommerce_checkout_order_processed as per below:
add_action( 'woocommerce_checkout_order_processed', 'get_order_items_on_checkout', 50, 3 );
function get_order_items_on_checkout($order_id, $posted_data, $order){
$items = $order->get_items();
}

Related

How to bulk change external column values defined in Orders table and stored in database?

I am working on return processes in Woocommerce. I am getting returned or not returned information from table named return_table. I added this information to a new column in the orders table. The table is simply as follows:
I need to make changes to the column I just added. For example, I want to update the value from no return to returned. For this, I should make a new definition in the default actions column or add a new bulk action. I decided to add bulk action as it is more functional:
However, I was unable to make any progress after that. I've done research on Stackoverflow or other platforms. I found an answer to add buttons (new actions) but still couldn't solve the problem:
Source-1
Others I've found are mostly geared towards changing the "Order Status":
Source-2, Source-3, Source-4...
So, i've been researching this for a while and haven't found a solution. I will be grateful if anyone can help.
My Code:
<?php
// Add new column
add_filter( 'manage_edit-shop_order_columns', 'return_column', 11);
function return_column( $columns ) {
$columns['return_column'] = 'Return Status';
return $columns;
}
// Add the data to the custom columns
add_action( 'manage_shop_order_posts_custom_column', 'return_column_content',11);
function return_column_content ($column){
if($column == 'return_column'){
// Create required global variables
global $post, $wpdb;
$order = wc_get_order( $post->ID );
$order_id = $order->get_id();
$result = $wpdb->get_results("SELECT return_status FROM {$wpdb->prefix}return_table WHERE order_id ='$order_id' LIMIT 1");
if(count($result)):
echo $result[0]->return_status;
else:
echo '-';
endif;
}
}
//Add new order status to bulk change
add_filter( 'bulk_actions-edit-shop_order', 'refund_register_bulk_action' );
function refund_register_bulk_action( $bulk_actions ) {
$bulk_actions['mark_returned'] = 'Returned';
$bulk_actions['mark_not_returned'] = 'Not Returned';
return $bulk_actions;
}

WooCommerce hook on order status change fires multiple times instead for only the changed order

I've created a hook for WooCommerce when an order is cancelled like so:
add_action( 'woocommerce_order_status_cancelled', 'prefix_order_cancelled_hook' );
function prefix_order_cancelled_hook($order_id){
write_log("Order ${order_id} has been cancelled")
}
Now when the status changed to cancelled, the hook is invoked as expected but the output execution is not what I'm expecting. I'm getting the following in the log:
Order 4 has been cancelled
Order 5 has been cancelled
Order 6 has been cancelled
I've seen that this corresponds to the number of orders I currently have on the store. Can someone help with why this is happening and how to only run the hook once for the changed order.
Seems like your code is executed for all orders. So there seems to be a problem with the $order_id. I think you can't access properties directly, but need to get an instance of the WC_Order object (since Woocommerce 3.0+ something about) like:
add_action( 'woocommerce_order_status_cancelled', 'prefix_order_cancelled_hook' );
function prefix_order_cancelled_hook($order_id){
// get an instance of an WC_Order object
$order = wc_get_order( $order_id );
// get the ID of the order
$order_id = $order->get_id();
write_log("Order ${order_id} has been cancelled")
}

WooCommerce woocommerce_new_order not firing when creating an order from the REST API

I have the following code snippet:
add_action('woocommerce_new_order', 'foo_function', 10);
If I create a new order from the admin panel, this fires just fine.
However, creating it via the REST API will not fire the function.
Why is that?
Update
I've tried using the following:
woocommerce_rest_insert_shop_object – this one doesn't fire at all.
wp_insert_post and save_post – they do fire, but don't contain the line items... (on the first run, it's an empty list, and on the second run (where the $update flag is true) there is an item but that item has no data (like product id or quantity).
add_action( "woocommerce_rest_insert_shop_order_object", 'your_prefix_on_insert_rest_api', 10, 3 );
function your_prefix_on_insert_rest_api( $object, $request, $is_creating ) {
if ( ! $is_creating ) {
return;
}
$order_id = $object->get_id();
$wc_order = new WC_Order( $order_id );
do_action( 'woocommerce_new_order', $order_id, $wc_order );
}
You have tried woocommerce_rest_insert_shop_object,
but the hook is woocommerce_rest_insert_shop_order_object
Please use this hook woocommerce_process_shop_order_meta instead of woocommerce_new_order As far as I can determine, woocommerce_new_order is only fired when an order is processed through the checkout. In a lot of instances, staff were creating orders in the wp-admin and assigning them straight to processing or completed, which meant that hook wasn't doing what I thought it would. Using woocommerce_process_shop_order_meta will solve it for you.
On v2 there is the woocommerce_rest_insert_{$this->post_type}_object filter
So the correct hook for what you need is woocommerce_rest_insert_shop_order_object

Woocommerce Get order items on checkout

I am trying to hook into a 3rd party application when a cart is checked out. Essentially i need to pass information about the order such as the products that are inside the order.
Everything i find points me towards the hook: woocommerce_new_order
When i use that hook i can get some information about the order but not everything.
add_action('woocommerce_new_order','order_check',10,1);
function order_check($order_id){
echo 'Order id is: '.$order_id;
$order = new WC_Order($order_id);
print_r($order);
echo '-----';
/** CHECK IF order has items */
$order_item = $order->get_items();
print_r($order_item);
exit;
}
For instance the above code sample will print the order array but when it call $order->get_items() nothing is returned.
At the time woocommerce_new_order fires, order items is not yet populated.
Instead, use the hook woocommerce_checkout_order_processed and you'll find that all items are then populated.

WooCommerce order-received endpoint and the order object

I am using the conditional is_wc_endpoint_url('order-received') in my header to check to see if the the 'page' is the Order Recieved end point, and if so I add some additional code to my Facebook Pixel code.
However I would like to access the order object as well so I can get the total of the order as well as check to see if it is actually complete ( get_status() ).
How can I access the order object from the order received end point?
Cheers
this worked for me
$order_key = $_GET['key'];
$order_id = wc_get_order_id_by_order_key($order_key);
$order = new WC_Order( $order_id );

Resources