WooCommerce - item added to order not actually saved?

admin2025-06-05  0

Closed. This question is off-topic. It is not currently accepting answers.

Your question should be specific to WordPress. Generic PHP/JS/SQL/HTML/CSS questions might be better asked at Stack Overflow or another appropriate Stack Exchange network site. Third-party plugins and themes are off-topic for this site; they are better asked about at their developers' support routes.

Closed 6 years ago.

Improve this question

I'm trying to make a plugin that merges two carts into one.

I am doing the following:

$old_order = wc_get_order($old_order_id);
duplicate_line_items($new_order, $old_order);
//re-fetch order to make sure changes aren't lost.
$new_order = $wc_get_order($new_order->get_id());
$new_order->calculate_totals();
$new_order->save_meta_data();
$new_order->save();

My duplicate_line_items() function looks like this:

function duplicate_line_items($source_order, $new_order){
    foreach ($source_order->get_items() as $item){
        $new_order->add_item($item);
    }
    $new_order->apply_changes();
    $new_order->save();
}

When I run this code, the items do not display in the admin view of the "new" order (the destination order), nor do they show up in the database.

I do see that per the WC_Order::add_item() docs, "The order item will not persist until save.", but I am saving the order, several times.

Am I missing a step here or something?

Thanks!

Closed. This question is off-topic. It is not currently accepting answers.

Your question should be specific to WordPress. Generic PHP/JS/SQL/HTML/CSS questions might be better asked at Stack Overflow or another appropriate Stack Exchange network site. Third-party plugins and themes are off-topic for this site; they are better asked about at their developers' support routes.

Closed 6 years ago.

Improve this question

I'm trying to make a plugin that merges two carts into one.

I am doing the following:

$old_order = wc_get_order($old_order_id);
duplicate_line_items($new_order, $old_order);
//re-fetch order to make sure changes aren't lost.
$new_order = $wc_get_order($new_order->get_id());
$new_order->calculate_totals();
$new_order->save_meta_data();
$new_order->save();

My duplicate_line_items() function looks like this:

function duplicate_line_items($source_order, $new_order){
    foreach ($source_order->get_items() as $item){
        $new_order->add_item($item);
    }
    $new_order->apply_changes();
    $new_order->save();
}

When I run this code, the items do not display in the admin view of the "new" order (the destination order), nor do they show up in the database.

I do see that per the WC_Order::add_item() docs, "The order item will not persist until save.", but I am saving the order, several times.

Am I missing a step here or something?

Thanks!

Share Improve this question edited Dec 6, 2018 at 19:53 butlerblog 5,1413 gold badges28 silver badges44 bronze badges asked Dec 6, 2018 at 19:11 Zachary CraigZachary Craig 993 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

You have your duplicate_line_items() function written so that the items from the first parameter, $source_order are added to the second parameter, $new_order, but in your first block of code you're passing the old order as the 2nd parameter:

duplicate_line_items($new_order, $old_order);

So all the items from $new_order are being added to $old_order, not the other way round.

Make sure you're using the variables consistently:

duplicate_line_items( $old_order, $new_order );

Maybe name your variables in duplicate_line_items() a bit more clearly too:

function duplicate_line_items( $source_order, $target_order ) {
    foreach ( $source_order->get_items() as $item ) {
        $target_order->add_item( $item );
    }

    $target_order->save();
}

So with those two changes you're properly setting $old_order as the $source_order and $new_order as the $target_order.

I've solved my issue, I misunderstood the functionality of wc_add_order_item()'s item_array parameter, and assumed that was for the item data.

The working function:

    /**
     *
     * Copy all line items from
     * 
     * @param $source_order \WC_Order
     * @param $destination_order \WC_Order
     */
    private function duplicate_line_items($source_order, $destination_order){
        //get all item types.
        foreach ($source_order->get_items(['line_item', 'shipping', 'tax']) as $item_id => $item){
            $data = $item->get_data();
            $data['order_id'] = $destination_order->get_id();
            $new_item_id = wc_add_order_item($destination_order->get_id(), ['order_item_name' => $item->get_name(), 'order_item_type' => $item->get_type()]);
            $meta = wc_get_order_item_meta($item_id);
            foreach ($meta as $meta_key => $meta_value){
                //needed incase there are multiple values for the same key: eg, ingredients.
                foreach ($meta_value as $number => $raw_value){
                    wc_add_order_item_meta($new_item_id, $meta_key, $raw_value);
                }
            }
        }
    }

Hopefully this helps someone else later :)

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1749120594a316537.html

最新回复(0)