如何通过产品 ID 获取包含订单 ID 的数组?
我的意思是接收所有展示特定产品的订单。
我知道如何通过 MySQL 执行此操作,但是有没有办法通过
WP_Query
函数执行此操作?
更新:
2024更新:
- 添加了更安全的 WPDB 准备()方法,双重强制函数参数作为查询中的整数。
- 添加了另一个功能,具有与高性能订单存储(HPOS)兼容的轻量级SQL查询。
2019 - 在 SQL 查询中启用产品变体类型支持
2017 - SQL 查询更改为
,而不是"SELECT DISTINCT"
,以避免重复数组中的订单ID(然后不需要"SELECT"
来过滤重复项... ).array_unique()
您可以将 SQL 查询嵌入到自定义函数中,并以
$product_id
作为参数。1)。全新轻量级SQL查询(兼容高性能订单存储HPOS)
WooCommerce 正在逐步迁移到自定义表格,以获得更好的性能。
从 2023 年 10 月发布的 WooCommerce 8.2 开始,高性能订单存储 (HPOS) 被正式标记为稳定,并将默认为新安装启用。
嵌入函数中的快速、轻量级 SQL 查询(兼容 HPOS):
// Get All defined statuses Orders IDs for a defined product ID (or variation ID)
function get_orders_ids_by_product_id( $product_id ) {
global $wpdb;
// HERE Define the orders status to include IN (each order status always starts with "wc-")
$orders_statuses = array('wc-completed', 'wc-processing', 'wc-on-hold');
// Convert order statuses array to a string for the query
$orders_statuses = "'" . implode("', '", $orders_statuses) . "'";
// The query
return $wpdb->get_col( $wpdb->prepare("
SELECT DISTINCT opl.order_id
FROM {$wpdb->prefix}wc_order_product_lookup opl,
{$wpdb->prefix}wc_orders o
WHERE opl.order_id = o.id
AND o.type = 'shop_order'
AND o.status IN ( {$orders_statuses} )
AND ( opl.product_id = %d OR opl.variation_id = %d )
ORDER BY opl.order_item_id DESC;", intval($product_id), intval($product_id) )
);
}
代码位于子主题的functions.php文件中(或插件中)。
经过测试并适用于 WooCommerce 版本 8+
2)。使用 WordPress 和 WooCommerce 旧表的旧经典 SQL 查询 (较重、效率较低且与 HPOS 不兼容):
// Get All defined statuses Orders IDs for a defined product ID (or variation ID)
function get_orders_ids_by_product_id( $product_id ) {
global $wpdb;
// HERE Define the orders status to include IN (each order status always starts with "wc-")
$orders_statuses = array('wc-completed', 'wc-processing', 'wc-on-hold');
// Convert order statuses array to a string for the query
$orders_statuses = "'" . implode("', '", $orders_statuses) . "'";
// The query
return $wpdb->get_col( $wpdb->prepare("
SELECT DISTINCT woi.order_id
FROM {$wpdb->prefix}woocommerce_order_itemmeta woim,
{$wpdb->prefix}woocommerce_order_items woi,
{$wpdb->prefix}posts p
WHERE woi.order_item_id = woim.order_item_id
AND woi.order_id = p.ID
AND p.post_status IN ( {$orders_statuses} )
AND woim.meta_key IN ( '_product_id', '_variation_id' )
AND woim.meta_value = %d
ORDER BY woi.order_item_id DESC;", intval($product_id) )
);
}
代码位于子主题的functions.php文件中(或插件中)。
经过测试并适用于 WooCommerce 版本 2.5+、2.6+ 和 3+
使用示例:
## This will display all orders containing this product ID in a coma separated string ##
// A defined product ID: 40
$product_id = 40;
// We get all the Orders for the given product ID in an arrray
$orders_ids = (array) get_orders_ids_by_product_id( $product_id );
// We display the orders count and the orders IDs in a coma separated string
printf( '<p>%d orders for IDs: %s</p>', count($orders_ids), implode( ', ', $orders_ids ) );
如果您希望您的代码在未来的 WC 更新中工作,最好使用 WC 提供的函数从 DB 获取详细信息,因为 WC 经常更改 DB 结构。 我会尝试这样的事情:
function get_orders_id_from_product_id($product_id, $args = array() ) {
//first get all the order ids
$query = new WC_Order_Query( $args );
$order_ids = $query->get_orders();
//iterate through order
$filtered_order_ids = array();
foreach ($order_ids as $order_id) {
$order = wc_get_order($order_id);
$order_items = $order->get_items();
//iterate through an order's items
foreach ($order_items as $item) {
//if one item has the product id, add it to the array and exit the loop
if ($item->get_product_id() == $product_id) {
array_push($filtered_order_ids, $order_id);
break;
}
}
}
return $filtered_order_ids;
}
使用示例:
$product_id = '2094';
// NOTE: With 'limit' => 10 you only search in the last 10 orders
$args = array(
'limit' => 10,
'orderby' => 'date',
'order' => 'DESC',
'return' => 'ids',
);
$filtered_order_ids = get_orders_id_from_product_id($product_id, $args);
print_r($filtered_order_ids);
我想指出,如果订单中有多个商品,上述答案将返回 order_id 的重复项。
例如
如果有一个名为“apples”的产品,其product_id=>1036
客户将“苹果”放入购物车 3 次并购买,创建 order_id=>555
如果我查询product_id->1036,我将得到数组(555,555,555)。
可能有一种 SQL 方法可以更快地执行此操作(将不胜感激任何可以添加此内容的人),否则我使用: array_unqiue() 来合并重复项。
function retrieve_orders_ids_from_a_product_id( $product_id )
{
global $wpdb;
$table_posts = $wpdb->prefix . "posts";
$table_items = $wpdb->prefix . "woocommerce_order_items";
$table_itemmeta = $wpdb->prefix . "woocommerce_order_itemmeta";
// Define HERE the orders status to include in <== <== <== <== <== <== <==
$orders_statuses = "'wc-completed', 'wc-processing', 'wc-on-hold'";
# Requesting All defined statuses Orders IDs for a defined product ID
$orders_ids = $wpdb->get_col( "
SELECT $table_items.order_id
FROM $table_itemmeta, $table_items, $table_posts
WHERE $table_items.order_item_id = $table_itemmeta.order_item_id
AND $table_items.order_id = $table_posts.ID
AND $table_posts.post_status IN ( $orders_statuses )
AND $table_itemmeta.meta_key LIKE '_product_id'
AND $table_itemmeta.meta_value LIKE '$product_id'
ORDER BY $table_items.order_item_id DESC"
);
// return an array of Orders IDs for the given product ID
$orders_ids = array_unique($orders_ids);
return $orders_ids;
}
修改函数以获取特定用户产品 ID
function retrieve_orders_ids_from_a_product_id( $product_id,$user_id )
{
global $wpdb;
$table_posts = $wpdb->prefix . "posts";
$table_postmeta = $wpdb->prefix . "postmeta";
$table_items = $wpdb->prefix . "woocommerce_order_items";
$table_itemmeta = $wpdb->prefix . "woocommerce_order_itemmeta";
// Define HERE the orders status to include in <== <== <== <== <== <== <==
$orders_statuses = "'wc-completed', 'wc-processing', 'wc-on-hold'";
# Requesting All defined statuses Orders IDs for a defined product ID
$orders_ids = $wpdb->get_col( "
SELECT DISTINCT $table_items.order_id
FROM $table_itemmeta, $table_items, $table_posts , $table_postmeta
WHERE $table_items.order_item_id = $table_itemmeta.order_item_id
AND $table_items.order_id = $table_posts.ID
AND $table_posts.post_status IN ( $orders_statuses )
AND $table_postmeta.meta_key LIKE '_customer_user'
AND $table_postmeta.meta_value LIKE '$user_id '
AND $table_itemmeta.meta_key LIKE '_product_id'
AND $table_itemmeta.meta_value LIKE '$product_id'
ORDER BY $table_items.order_item_id DESC"
);
// return an array of Orders IDs for the given product ID
return $orders_ids;
}
使用示例
## This will display all orders containing this product ID in a coma separated string ##
// A defined product ID: 40
$product_id = 40;
// Current User
$current_user = wp_get_current_user();
// We get all the Orders for the given product ID of current user in an arrray
$orders_ids_array = retrieve_orders_ids_from_a_product_id( $product_id, $current_user->ID );
// We display the orders in a coma separated list
echo '<p>' . implode( ', ', $orders_ids_array ) . '</p>';