Get User Orders WooCommerce
February 20, 2025 Β· AI Conversations
### **1. Using `WC_Order_Query` (Recommended)**
This approach leverages WooCommerce's built-in functions:
function get_orders_by_user($user_id) {
$args = [
'customer_id' => $user_id,
'status' => 'any', // Retrieves orders with any status
'limit' => -1, // No limit, fetch all orders
];
$orders = wc_get_orders($args);
return $orders;
}
// Example usage
$user_id = get_current_user_id(); // Get the current logged-in user's ID
$orders = get_orders_by_user($user_id);
foreach ($orders as $order) {
echo 'Order ID: ' . $order->get_id() . '<br>';
echo 'Total: ' . wc_price($order->get_total()) . '<br>';
}
—
### **2. Using Direct Database Query**
If you need a more optimized query, you can fetch order IDs directly from the database:
global $wpdb;
$user_id = get_current_user_id(); // Change this if needed
$orders = $wpdb->get_results("
SELECT ID FROM {$wpdb->prefix}posts
WHERE post_type = 'shop_order'
AND post_author = $user_id
ORDER BY post_date DESC
");
foreach ($orders as $order) {
$wc_order = wc_get_order($order->ID);
echo 'Order ID: ' . $wc_order->get_id() . '<br>';
echo 'Total: ' . wc_price($wc_order->get_total()) . '<br>';
}
—
### **3. Using REST API (If needed for external use)**
If you need to fetch orders via an API, you can use the WooCommerce REST API:
add_action('rest_api_init', function () {
register_rest_route('custom/v1', '/user-orders/', [
'methods' => 'GET',
'callback' => 'get_user_orders_rest',
'permission_callback' => function () {
return is_user_logged_in();
}
]);
});
function get_user_orders_rest($request) {
$user_id = get_current_user_id();
if (!$user_id) {
return new WP_Error('no_user', 'User not found', ['status' => 403]);
}
$orders = wc_get_orders(['customer_id' => $user_id, 'status' => 'any', 'limit' => -1]);
$data = [];
foreach ($orders as $order) {
$data[] = [
'order_id' => $order->get_id(),
'total' => $order->get_total(),
'status' => $order->get_status(),
'date' => $order->get_date_created()->date('Y-m-d H:i:s'),
];
}
return rest_ensure_response($data);
}
You can then call the API using:
GET /wp-json/custom/v1/user-orders/
—
#### **Which method should you use?**
– **Method 1 (`WC_Order_Query`)** β Best for general WooCommerce queries.
– **Method 2 (Direct DB Query)** β Use if you want optimized queries.
– **Method 3 (REST API)** β If you need to fetch orders via API.
Let me know if you need modifications based on your setup! π
### **1. Using `WC_Order_Query` (Recommended)**
function get_users_order_count() {
global $wpdb;
$results = $wpdb->get_results("
SELECT post_author as user_id, COUNT(ID) as order_count
FROM {$wpdb->prefix}posts
WHERE post_type = 'shop_order'
AND post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold', 'wc-pending', 'wc-cancelled', 'wc-failed', 'wc-refunded')
GROUP BY post_author
ORDER BY order_count DESC
");
if (!$results) {
echo "<p>No orders found.</p>";
return;
}
echo "<table border='1'>";
echo "<tr><th>User ID</th><th>User Name</th><th>Number of Orders</th></tr>";
foreach ($results as $row) {
$user_info = get_userdata($row->user_id);
$user_name = $user_info ? $user_info->display_name : 'Guest User';
echo "<tr>";
echo "<td>{$row->user_id}</td>";
echo "<td>{$user_name}</td>";
echo "<td>{$row->order_count}</td>";
echo "</tr>";
}
echo "</table>";
}
// Call the function to display the data
get_users_order_count();
—
### **How it Works?**
– Fetches all unique users (`post_author`) who have placed orders.
– Counts the number of orders per user.
– Retrieves user details (name) using `get_userdata()`.
– Displays the data in a table format.
—
### **Alternative: Get Users and Orders Using `wc_get_orders()`**
If you prefer WooCommerce's built-in methods, you can use this:
function get_users_order_count_wc() {
$args = [
'limit' => -1,
'return' => 'ids', // Only get order IDs
];
$orders = wc_get_orders($args);
$user_orders = [];
foreach ($orders as $order_id) {
$order = wc_get_order($order_id);
$user_id = $order->get_user_id();
if ($user_id) {
if (!isset($user_orders[$user_id])) {
$user_orders[$user_id] = 0;
}
$user_orders[$user_id]++;
}
}
echo "<table border='1'>";
echo "<tr><th>User ID</th><th>User Name</th><th>Number of Orders</th></tr>";
foreach ($user_orders as $user_id => $order_count) {
$user_info = get_userdata($user_id);
$user_name = $user_info ? $user_info->display_name : 'Guest User';
echo "<tr>";
echo "<td>{$user_id}</td>";
echo "<td>{$user_name}</td>";
echo "<td>{$order_count}</td>";
echo "</tr>";
}
echo "</table>";
}
// Call the function
get_users_order_count_wc();
—
### **Which One Should You Use?**
– **First method (SQL Query)** β Faster and more optimized for large stores.
– **Second method (`wc_get_orders()`)** β Better if you want to use WooCommerceβs built-in functions.
Let me know if you need modifications! π
Now display each unqiues user and their order count
—
### **Optimized Query Using SQL (Recommended for Performance)**
function get_unique_users_order_count() {
global $wpdb;
$results = $wpdb->get_results("
SELECT meta_value as user_id, COUNT(post_id) as order_count
FROM {$wpdb->prefix}postmeta
WHERE meta_key = '_customer_user'
AND meta_value > 0
GROUP BY meta_value
ORDER BY order_count DESC
");
if (!$results) {
echo "<p>No orders found.</p>";
return;
}
echo "<table border='1'>";
echo "<tr><th>User ID</th><th>User Name</th><th>Email</th><th>Number of Orders</th></tr>";
foreach ($results as $row) {
$user_info = get_userdata($row->user_id);
$user_name = $user_info ? $user_info->display_name : 'Unknown User';
$user_email = $user_info ? $user_info->user_email : 'N/A';
echo "<tr>";
echo "<td>{$row->user_id}</td>";
echo "<td>{$user_name}</td>";
echo "<td>{$user_email}</td>";
echo "<td>{$row->order_count}</td>";
echo "</tr>";
}
echo "</table>";
}
// Call the function to display the data
get_unique_users_order_count();
—
### **Explanation:**
1. Queries the `wp_postmeta` table where `_customer_user` is stored.
2. Counts the number of orders per user.
3. Retrieves the user's name and email from `wp_users` using `get_userdata()`.
4. Displays the results in an HTML table.
—
### **Alternative Using `wc_get_orders()` (Less Efficient)**
If you prefer using WooCommerce's built-in functions:
function get_users_order_count_wc() {
$args = [
'limit' => -1,
'return' => 'ids',
];
$orders = wc_get_orders($args);
$user_orders = [];
foreach ($orders as $order_id) {
$order = wc_get_order($order_id);
$user_id = $order->get_customer_id();
if ($user_id) {
if (!isset($user_orders[$user_id])) {
$user_orders[$user_id] = 0;
}
$user_orders[$user_id]++;
}
}
echo "<table border='1'>";
echo "<tr><th>User ID</th><th>User Name</th><th>Email</th><th>Number of Orders</th></tr>";
foreach ($user_orders as $user_id => $order_count) {
$user_info = get_userdata($user_id);
$user_name = $user_info ? $user_info->display_name : 'Unknown User';
$user_email = $user_info ? $user_info->user_email : 'N/A';
echo "<tr>";
echo "<td>{$user_id}</td>";
echo "<td>{$user_name}</td>";
echo "<td>{$user_email}</td>";
echo "<td>{$order_count}</td>";
echo "</tr>";
}
echo "</table>";
}
// Call the function
get_users_order_count_wc();
—
### **Which One to Use?**
– **First method (SQL Query)** β **Faster** for large stores, directly fetches data from `wp_postmeta`.
– **Second method (`wc_get_orders()`)** β Uses WooCommerce functions but can be slower for large databases.
Let me know if you need modifications! π
with pagination
—
### **1. PHP Function with Pagination**
function get_unique_users_order_count_paginated($page = 1, $per_page = 10) {
global $wpdb;
$offset = ($page - 1) * $per_page;
// Get total count of unique users
$total_users = $wpdb->get_var("
SELECT COUNT(DISTINCT meta_value)
FROM {$wpdb->prefix}postmeta
WHERE meta_key = '_customer_user'
AND meta_value > 0
");
// Fetch paginated results
$results = $wpdb->get_results($wpdb->prepare("
SELECT meta_value as user_id, COUNT(post_id) as order_count
FROM {$wpdb->prefix}postmeta
WHERE meta_key = '_customer_user'
AND meta_value > 0
GROUP BY meta_value
ORDER BY order_count DESC
LIMIT %d OFFSET %d
", $per_page, $offset));
if (!$results) {
echo "<p>No orders found.</p>";
return;
}
echo "<table border='1'>";
echo "<tr><th>User ID</th><th>User Name</th><th>Email</th><th>Number of Orders</th></tr>";
foreach ($results as $row) {
$user_info = get_userdata($row->user_id);
$user_name = $user_info ? $user_info->display_name : 'Unknown User';
$user_email = $user_info ? $user_info->user_email : 'N/A';
echo "<tr>";
echo "<td>{$row->user_id}</td>";
echo "<td>{$user_name}</td>";
echo "<td>{$user_email}</td>";
echo "<td>{$row->order_count}</td>";
echo "</tr>";
}
echo "</table>";
// Pagination Links
$total_pages = ceil($total_users / $per_page);
echo "<div class='pagination'>";
for ($i = 1; $i <= $total_pages; $i++) {
echo "<a href='?page=$i' " . ($i == $page ? "style='font-weight:bold;'" : "") . "> $i </a> ";
}
echo "</div>";
}
// Get current page from URL
$current_page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
// Call function with pagination
get_unique_users_order_count_paginated($current_page, 10);
—
### **How It Works?**
1. **Pagination Logic**
– `$page`: Fetches the current page number from `$_GET['page']`, defaulting to `1`.
– `$per_page`: Defines the number of records per page.
– `$offset`: Calculates the offset for SQL query.
2. **Querying the Database**
– First, we get the **total number of unique users**.
– Then, we fetch **paginated records** using `LIMIT %d OFFSET %d`.
3. **Displaying Pagination Links**
– Generates numbered pagination links.
– Highlights the current page.
—
### **How to Use?**
– Just add `?page=2`, `?page=3`, etc., in the URL to navigate.
– Modify `$per_page = 10` to adjust the number of results per page.
—
### **Example Output**
-------------------------------------------------
| User ID | User Name | Email | Orders |
-------------------------------------------------
| 12 | John Doe | john@email.com | 5 |
| 18 | Jane Smith | jane@email.com | 4 |
-------------------------------------------------
[1] [2] [3] [Next]
This is optimized for large WooCommerce stores. Let me know if you need any modifications! π