4

With WooCommerce, I have the following hook in my function.php after the new order is submitted:

add_action( 'woocommerce_new_order', 'create_job_openings');
function create_job_openings($order_id) {

    $order = new WC_Order($order_id);
    $items = $order->get_items();

    foreach ($order->get_items() as $key => $item) {
        $product_name = $item['name'];
        var_dump($product_name);
    }
}

The above code is not giving me any output i'e it is not entering inside the foreach loop that's why var_dump() not giving me any output, but if I mention the order_id specifically like create_job_openings($order_id=517) it works, even I tried echo $order_id before foreach loop, it is giving me the order_id, then why it is not entering the foreach loop?

note: when I try var_dump($items); before foreach loop its giving me

array(0) {
} 

Why it is not able to get the product details even if there are products in it after new order is made?

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
sam
  • 271
  • 6
  • 23

4 Answers4

6

Update 2 — The working solution (using an email notification hook)

The problem is when using email notification hook can fire an action 2 times, for example when a new order is made (notification for the Shop manager and notification for the customer).

You want to use this "New Order" event for Orders that are in "processing" status.

To avoid your action to be fired 2 times using New order notification WooCommerce event, we use 'customer_processing_order' instead of 'new_order' email ID (notification event).

Here we don't need to get the $order object, as we got it as an argument in this hooked function.

So here is your final functional code:

add_action( 'woocommerce_email_before_order_table', 'custom_action_on_completed_customer_email_notification', 10, 4 );
function custom_action_on_completed_customer_email_notification( $order, $sent_to_admin, $plain_text, $email ) {

    if( 'customer_processing_order' == $email->id ){ // for processing order status customer notification…
        foreach ($order->get_items() as $item_id => $item_values) {
            $product_name = $item_values['name'];
            echo $product_name;
            break; // (optional) stop loop to first item
        }
    }
}

This is the validated and working answer to this question

Related Working Answers:


Update 1 (hook alternative)

Trying using woocommerce_thankyou hook, that is fired on review order after order has been processed:

add_action( 'woocommerce_thankyou', 'create_job_openings', 10, 1 );
function create_job_openings( $order_id ) {
    if ( ! $order_id )
        return;
    
    $order = wc_get_order( $order_id );
    
    foreach ($order->get_items() as $item_id => $item_values) {
        $product_name = $item_values['name'];
        var_dump($product_name);
        break; // (optional) stop loop to first item
    }
}

(Not working for the OP)


You should try this instead wc_get_order() function this way and your code will be:

add_action( 'woocommerce_new_order', 'create_job_openings', 10, 1);
function create_job_openings($order_id) {

    $order = wc_get_order( $order_id );
    $order_items = $order->get_items();

    foreach ($order_items as $item_id => $item_values) {
        $product_name = $item_values['name'];
        var_dump($product_name);
        break; // (optional) stops on first item
    }
}

You can have a look to How to get WooCommerce order details where a lot of things are explained…

(Not working for the OP)

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
1

you can use save_post action when post is added in wordpress. for more visit: Link

function wc_order_add_action($post_id, $post, $update)
{
    $post_type = get_post_type($post_id);

    // If this isn't a 'shop_order' post, don't update it.
    if ("shop_order" != $post_type) return;

    $order = wc_get_order($post_id);

    foreach($order -> get_items() as $key => $item)
    {
        $product_name = $item['name'];
        var_dump($product_name);
    }
}
add_action('save_post', 'wc_order_add_action');
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
vrajesh
  • 2,935
  • 3
  • 25
  • 40
1

To get the items and product details from the new order, you simply need to request two parameters for woocommerce_new_order. The second passed parameter will be the new order object. Example:

add_action( 'woocommerce_new_order', 'so41605256_new_order', 10, 2 );
function so41605256_new_order( $order_id, $order ) {
    // Directly access items from $order variable, do not use wc_get_order...
    foreach ($order->get_items() as $item_id => $item) {
        //...
    }
}

This works for both programmatically created and user created orders, regardless of WC email configuration.

Reference: create and update methods in WC_Order_Data_Store_CPT core class. Kudos to this post which helped me discover this.

N Rohler
  • 4,595
  • 24
  • 20
0

Faced the same issue. I fixed it by changing the hook to woocommerce_checkout_order_processed. It works perfectly for both instant payment and cash on delivery since it runs as soon as an order is placed. Note that, this will run before payment completion. So, it doesn't have any relation with payment.

User clicks on proceed to checkout button and then this hook fires.

Mehbub Rashid
  • 553
  • 6
  • 6