Get products from last orders in WooCommerce

Issue

I want to show the last 10 products a user has ordered in the past.

The problem is, that I don’t know how many products where in the last order.
So I maybe need to get more than one order.

I want to display everything in the cart. To let users buy products again.
Later I want to exclude procuts which are in the current cart.

For the last order I found a snippet here: https://stackoverflow.com/a/71501798/1788961

// For logged in users only
if ( is_user_logged_in() ) {

    // The current user ID
    $user_id = get_current_user_id();

    // Get the last WC_Order Object instance from current customer
    $last_order = wc_get_customer_last_order( $user_id );

    // NOT empty
    if ( ! empty( $last_order ) ) {
        // Initalize
        $product_ids = array();

        // Loop
        foreach ( $last_order->get_items() as $item ) {
            // Get product ID
            $product_id = $item->get_product_id();
            $product_ids[] = $product_id;
        }

        echo '<pre>';
        var_dump( $product_ids );
        echo '</pre>';
    }
}

Is there a way to extend the function to more orders?

Solution

You can indeed use wc_get_orders(), where you will retrieve the orders based on arguments, such as the user ID and order by date.

Also note that a limit of 10 is used. This is because we can assume that every order contains at least 1 product. So if you want to collect 10 products the limit will never be more than 10 orders:

// Args
$args = array(
    'customer_id'   => get_current_user_id(),
    'limit'         => 10,
    'orderby'       => 'date',
    'order'         => 'DESC',
    'status'        => array( 'wc-on-hold','wc-processing','wc-completed' ),
);

// Get orders
$orders = wc_get_orders( $args );

// NOT empty
if ( ! empty ( $orders ) ) {
    // Initalize
    $product_ids = array();

    foreach ( $orders as $order ) {
        // Loop through order items
        foreach ( $order->get_items() as $item ) {
            // Get product ID
            $product_id = $item->get_product_id();

            // Limit of 10 products
            if ( count( $product_ids ) < 10 ) {
                // Push to array
                $product_ids[] = $product_id;
            } else {
                break;
            }
        }
    }

    // The output
    echo '<pre>', print_r( $product_ids, 1 ), '</pre>';
}

A much lighter and faster solution is to use a custom SQL query:

global $wpdb;

$current_user = wp_get_current_user();
$customer_email = $current_user->user_email;

$result = $wpdb->get_col( "
    SELECT oim.meta_value FROM {$wpdb->prefix}posts AS p
    INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
    INNER JOIN {$wpdb->prefix}woocommerce_order_items AS oi ON p.ID = oi.order_id
    INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS oim ON oi.order_item_id = oim.order_item_id
    WHERE p.post_status IN ( 'wc-on-hold','wc-processing','wc-completed' )
    AND pm.meta_key = '_billing_email'
    AND pm.meta_value = '$customer_email'
    AND oim.meta_key = '_product_id'
    AND oim.meta_value != 0
    ORDER BY p.post_date DESC LIMIT 0, 10
" );

// The raw output
echo '<pre>', print_r( $result, 1 ), '</pre>';

Whichever option you prefer. These can in any case be expanded with, for example, the variants, of variable products or on the basis of multiple order statuses. Excluding duplicate products, etc.. So it depends on your needs

Answered By – 7uc1f3r

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published