I am using this to get the data from the latest completed order:
<?php
function get_last_order_id(){
global $wpdb;
$statuses = "wc-completed";
// Getting last Order ID (max value)
$results = $wpdb->get_col( "
SELECT MAX(ID) FROM {$wpdb->prefix}posts
WHERE post_type LIKE 'shop_order'
AND post_status IN ('$statuses')
" );
return reset($results);
}
$latest_order_id = get_last_order_id(); // Last order ID
echo ($latest_order_id);
$order = wc_get_order( $latest_order_id );
$order_data = $order->get_data();
print_r($order);
However, the data that I need to get is showing as this:
[data:protected] => Array ( [id] => 3767 [key] => billing_name [value] => David) )
I have searched the questions on the StackOverflow on this but unfortunately, I still can't access this. Does anyone have an idea of how I can get it?
Thanks in Advance
<?php
function get_last_order_id(){
global $wpdb;
$statuses = "wc-completed";
// Getting last Order ID (max value)
$results = $wpdb->get_row( "SELECT MAX(P.ID) ,PM.meta_value as firstname
FROM {$wpdb->prefix}posts AS P
INNER JOIN {$wpdb->prefix}postmeta AS PM
ON P.ID = PM.post_id
WHERE P.post_type LIKE 'shop_order'
AND P.post_status IN ('$statuses')
AND PM.meta_key='_billing_first_name'" );
return $results;
}
$latest_order_id = get_last_order_id(); // Last order ID
$firstname = $latest_order_id->firstname;
echo $firstname;
Related
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?
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
After buying a product add this product order ID in this user meta. I can check the product bought status using this wc_customer_bought_product(). Now I need to get this product order id using UserID and product ID. How can I achieve this? My ultimate goal is after getting order id I will remove order by this function wp_delete_post()
$bronze = wc_customer_bought_product($current_user->user_email, $current_user->ID, 246014);
function get_customerorderid(){
global $post;
$order_id = $post->ID;
// Get an instance of the WC_Order object
$order = wc_get_order($order_id);
// Get the user ID from WC_Order methods
$user_id = $order->get_user_id(); // or $order->get_customer_id();
return $user_id;
}
get_customerorderid();
wp_delete_post(246014,true);
You can do that making a custom sql query embedded in a function, using WPDB Class, this way:
function get_completed_orders_for_user_from_product_id( $product_id, $user_id = 0 ) {
global $wpdb;
$order_status = 'wc-completed';
// If optional $user_id argument is not set, we use the current user ID
$customer_id = $user_id === 0 ? get_current_user_id() : $user_id;
// Return customer orders IDs containing the defined product ID
return $wpdb->get_col( $wpdb->prepare("
SELECT DISTINCT woi.order_id
FROM {$wpdb->prefix}posts p
INNER JOIN {$wpdb->prefix}postmeta pm
ON p.ID = pm.post_id
INNER JOIN {$wpdb->prefix}woocommerce_order_items woi
ON p.ID = woi.order_id
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta woim
ON woi.order_item_id = woi.order_item_id
WHERE p.post_status = '%s'
AND pm.meta_key = '_customer_user'
AND pm.meta_value = '%d'
AND woim.meta_key IN ( '_product_id', '_variation_id' )
AND woim.meta_value LIKE '%d'
ORDER BY woi.order_item_id DESC
", $order_status, $customer_id, $product_id ) );
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
USAGE with wp_delete_post() to remove related orders containing a specific product (id: 246014):
// Get all orders containing 246014 product ID for the current user
$orders_ids = get_completed_orders_for_user_from_product_id( 246014 );
// Checking that, the orders IDs array is not empty
if( count($orders_ids) > 0 ) {
// Loop through orders IDs
foreach ( $orders_ids as $order_id ) {
// Delete order post data
wp_delete_post( $order_id, true );
}
// Add the order(s) ID(s) in user meta (example)
update_user_meta( get_current_user_id(), 'item_246014', implode( ',', $orders_ids ) );
}
Related threads:
Get all Orders IDs from a product ID in Woocommerce
Changing WooCommerce processing orders status based on product stock quantity
I have the products ids as an array and I would like to get the list of order ids if the customer has purchased that product.
I have the customer purchased product ids with me. Somehow, I have to get the linked order id and cancel that order if customer purchases new product.
To check if a customer has purchased a product I am using the function has_bought_items() from this answer thread: Check if a customer has purchased a specific products in WooCommerce
May be it can be tweaked to get the desired output?
The following custom function made with a very light unique SQL query, will get all the Orders IDs from an array of products IDs (or a unique product ID) for a given customer.
Based on code from: Check if a customer has purchased a specific products in WooCommerce
function get_order_ids_from_bought_items( $product_ids = 0, $customer_id = 0 ) {
global $wpdb;
$customer_id = $customer_id == 0 || $customer_id == '' ? get_current_user_id() : $customer_id;
$statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );
if ( is_array( $product_ids ) )
$product_ids = implode(',', $product_ids);
if ( $product_ids != ( 0 || '' ) )
$meta_query_line = "AND woim.meta_value IN ($product_ids)";
else
$meta_query_line = "AND woim.meta_value != 0";
// Get Orders IDs
$results = $wpdb->get_col( "
SELECT DISTINCT p.ID 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 woi ON p.ID = woi.order_id
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
AND pm.meta_key = '_customer_user'
AND pm.meta_value = $customer_id
AND woim.meta_key IN ( '_product_id', '_variation_id' )
$meta_query_line
" );
// Return an array of Order IDs or an empty array
return sizeof($results) > 0 ? $results : array();
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
USAGE Examples:
1) For the current logged in customer (and 2 product Ids in an array):
$product_ids = array(37,53);
$order_ids = get_order_ids_from_bought_items( $product_ids );
2) For a defined User ID and one product ID:
$product_id = 53;
$user_id = 72;
$order_ids = get_order_ids_from_bought_items( $product_id, $user_id );
I need help in rewriting the query below to accept a second and a second + third qualification.
Example meta keys and values:
Trees
meta_key = trees
meta_value = pine, oak, sequoia
States
meta_key = states
meta_value = california, washington, florida
Countries
meta_key = countries
meta_value = usa, uk, ireland
I attempted to add these AND statements but I was not able to cause it to work properly.
Second qualification:
AND (pm.meta_key = 'states' AND pm.meta_value = 'california')
Second and third qualification:
AND (pm.meta_key = 'states' AND pm.meta_value = 'california')
AND (pm.meta_key = 'countires' AND pm.meta_value = 'usa')
Function with query I need help in rewritting:
function get_unique_post_meta_values( $key = 'trees', $type = 'post', $status = 'publish' ) {
global $wpdb;
if( empty( $key ) )
return;
$res = $wpdb->get_col( $wpdb->prepare( "
SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
WHERE pm.meta_key = '%s'
AND p.post_status = '%s'
AND p.post_type = '%s'
", $key, $status, $type ) );
return $res;
}
Thanks in advance for your help! Please let me know if further clarification is required.
If the function sets $key=trees, what is the point of an empty check? Additionally, I think you are missing the curly brackets. You are selecting 'pm.meta_value', which is why are you doing a LEFT JOIN, I think? Maybe seeing your DB structure would help me understand that, but an INNER JOIN is what you want.
if( empty( $key ) ){
return;
} else {
$res = $wpdb->get_col( $wpdb->prepare( "
SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} as p ON p.ID = pm.post_id
WHERE pm.meta_key = '%s'
AND p.post_status = '%s'
AND p.post_type = '%s'
", $key, $status, $type ) );
return $res;
}
Try this. If it doesn't work then update this question with more details and I will help guide you further.
I am running a competition which is based on WP Custom Fields. I am trying to count all meta values of a meta_key='odd' for a specific user. I am using the formula below but it's not returning any result.
$meta_key = 'odd';
$post_author = 'Admin';
$odd = $wpdb->get_var( $wpdb->prepare(
"
SELECT Count(meta_value)
FROM $wpdb->postmeta
INNER JOIN $wpdb->posts ON $wpdb->postmeta->post_id = $wpdb->posts->ID
WHERE $wpdb->postmeta->meta_key = 'odd' AND $wpdb->posts->post_author = 'Admin'
",
$meta_key, $post_author
) );
echo "<p>Total odd {$odd}</p>";
Anyone can help me? Thanks in advance.
You are mixing up the $wpdb variables and the $post variables - for your JOIN, for example, you can't use $wpdb->postmeta->post_id, it would be {$wpdb->postmeta}.post_id, and would be even better to just use table aliases. Your prepare() is also not passing in your meta_key or author because you don't have %s placeholders for them
$odd = $wpdb->get_var( $wpdb->prepare(
"
SELECT count(meta_value)
FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID
WHERE pm.meta_key = %s AND p.post_author = %s
",
$meta_key, $post_author
) );