Daman
Daman

Reputation: 521

How to get all orders of current user in woocommerce

I want to get all orders made by current user inside a plugin function.

I'm using this:

    function get_all_orders(){
        $customer_orders = get_posts( apply_filters( 'woocommerce_my_account_my_orders_query', array(
            'numberposts' => $order_count,
            'meta_key'    => '_customer_user',
            'meta_value'  => get_current_user_id(),
            'post_type'   => wc_get_order_types( 'view-orders' ),
            'post_status' => array_keys( wc_get_order_statuses() )
        ) ) );
   return $customer_orders;
  }

This works well inside theme but inside custom plugin it doesn't return anything. Am i doing something wrong? Should i call some WooCommerce class first?

Upvotes: 14

Views: 28398

Answers (3)

JoeMoe1984
JoeMoe1984

Reputation: 2032

I want to advise against the function wc_get_orders for large databases with lots of orders. While this will give you the result you are looking for, the sql query it generates is insanely slow.

We used this on a t3.medium database instance on AWS and we were getting 100+ seconds for the generated query to return the results.

Not sure if there are proper Woocommerce functions to do this efficiently but here is how we got a users orders.

Functions to query the Woocommerce tables

/**
 * Woocommerce allows users to purchase products without creating an account.
 * They store the email and other details in the customer lookup table giving them a customer id.
 * Use this function if you need to get orders for a customer that does not have a user account.
 */
function my_get_customer_by_email($email)
{
  global $wpdb;
  $sql = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wc_customer_lookup WHERE email = %s", $email);
  if (!$sql) {
    return new WP_Error('Error in customer query');
  }
  return $wpdb->get_row($sql);
}

function my_get_customer_by_user_id($id)
{
  global $wpdb;
  $sql = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wc_customer_lookup WHERE user_id = %d", $id);
  if (!$sql) {
    return new WP_Error('Error in customer query');
  }
  return $wpdb->get_row($sql);
}

/**
 * Get all orders by a customer
 */
function my_get_customers_orders($customer_id)
{
  global $wpdb;
  $sql = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wc_order_stats WHERE customer_id = %d", $customer_id);
  if (!$sql) {
    return new WP_Error('Error in order query');
  }
  return $wpdb->get_results($sql);
}

/**
 * Get all completed orders by a customer
 */
function my_get_completed_customers_orders($customer_id)
{
  global $wpdb;
  $sql = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wc_order_stats WHERE customer_id = %d AND status='wc-completed'", $customer_id);
  if (!$sql) {
    return new WP_Error('Error in order query');
  }
  return $wpdb->get_results($sql);
}

Here is an example on how to use the previous functions:

// get the customer by the users id
$customer = my_get_customer_by_user_id($user_id);
if(is_wp_error($customer)) {
  // handle possible sql error here
  // error_log($customer->get_error_message());
}

if(!$customer) {
  // handle customer not found logic here
}

$orders = my_get_customers_orders($customer->customer_id);

If you need these to be WC_Order objects you can add this additional logic:

function map_orders_to_objects($o) {
  return new WC_Order($o->order_id);
}

$wc_orders = array_map('map_orders_to_object', $orders);

// you now have access to the orders line items
foreach($orders as $order) {
  $items = $order->get_items();
  // do something with the items
}

We went from 100+ seconds down to about 1s (estimated) just to get a customers orders. It was magnitudes faster than using wc_get_orders. Any query, that needs to query an indexable item, like a customer_id in the postsmeta table or any meta table should be avoided. Wordpress functions give you so many tools to shoot yourself in the foot for convenience.

Upvotes: 0

kontur
kontur

Reputation: 5217

The API might have changed since the original question, but this is a lot more elegant and uses WC’s own functions:

$args = array(
    'customer_id' => $user_id,
    'limit' => -1, // to retrieve _all_ orders by this user
);
$orders = wc_get_orders($args);

You can use many more other $args.

Upvotes: 29

mujuonly
mujuonly

Reputation: 11841

    if (!class_exists('WooCommerce')) :
        require ABSPATH . 'wp-content/plugins/woocommerce/woocommerce.php';
        $orders = get_all_orders();
    endif;

    function get_all_orders() {
        $customer_orders = get_posts(apply_filters('woocommerce_my_account_my_orders_query', array(
            'numberposts' => -1,
            'meta_key' => '_customer_user',
            'meta_value' => get_current_user_id(),
            'post_type' => wc_get_order_types('view-orders'),
            'post_status' => array_keys(wc_get_order_statuses())
                )));
        return $customer_orders;
    }

Try this code.

Upvotes: 2

Related Questions