如何在WooCommerce中通过get_users()参数按最近订单排序用户
嘿,这个需求在WooCommerce里挺常见的,刚好我有靠谱的方案可以分享给你~
按用户最近订单排序的实现方法
首先得说清楚:get_users()本身的默认参数里没有直接按订单排序的选项,因为用户数据存在wp_users表,而订单存在wp_posts表(类型为shop_order),两者是通过用户ID关联的,所以需要自定义查询逻辑。
下面给你两种可行的方案,优先推荐第一种(效率更高):
方案一:通过钩子修改用户查询(数据库层面关联)
这种方法是利用pre_user_query钩子,直接修改WP_User_Query的SQL语句,关联订单表并按最新订单日期排序,性能最优,适合用户量较大的场景。
步骤1:添加钩子函数
把这段代码放到你的主题functions.php或者自定义插件里:
add_action( 'pre_user_query', 'sort_users_by_latest_woocommerce_order' ); function sort_users_by_latest_woocommerce_order( $query ) { // 只在我们指定排序方式时触发,避免影响全局用户查询 if ( ! isset( $query->query_vars['orderby'] ) || $query->query_vars['orderby'] !== 'latest_order' ) { return; } global $wpdb; // 关联订单表,筛选有效状态的订单(可按需调整) $query->query_from .= " LEFT JOIN {$wpdb->prefix}posts AS orders ON {$wpdb->users}.ID = orders.post_author AND orders.post_type = 'shop_order' AND orders.post_status IN ('wc-completed', 'wc-processing') "; // 按最新订单日期降序排序,没有订单的用户按注册时间兜底 $query->query_orderby = " MAX(orders.post_date) DESC, {$wpdb->users}.user_registered DESC "; // 去重,避免一个用户多个订单导致重复结果 $query->query_fields = 'DISTINCT ' . $query->query_fields; }
步骤2:调用get_users()时指定排序参数
现在你可以像这样获取按最近订单排序的用户了:
$users = get_users( array( 'orderby' => 'latest_order', // 对应钩子里的自定义排序标识 'order' => 'DESC', // 降序,最近下单的在前 'role' => 'customer', // 可选:只获取客户角色的用户 // 其他参数比如number、offset等按需添加 ) );
小提示
- 如果你想包含其他状态的订单(比如“待付款”
wc-on-hold),直接修改IN里的状态值即可; - 没有订单的用户会被放到最后,按注册时间排序。
方案二:手动获取用户后排序(适合小用户量)
如果你的网站用户不多,也可以先获取所有用户,再逐个查询他们的最新订单日期,最后手动排序数组。这种方法代码更直观,但性能不如第一种。
示例代码:
// 获取所有用户(可添加role等筛选参数) $users = get_users( array( 'role' => 'customer' ) ); // 给每个用户添加最新订单时间戳 foreach ( $users as $user ) { // 查询用户的最新订单 $latest_order = wc_get_orders( array( 'customer_id' => $user->ID, 'status' => array( 'wc-completed', 'wc-processing' ), 'limit' => 1, 'orderby' => 'date', 'order' => 'DESC', ) ); // 把最新订单日期转为时间戳,没有订单则设为0 $user->latest_order_date = ! empty( $latest_order ) ? $latest_order[0]->get_date_created()->getTimestamp() : 0; } // 按最新订单日期降序排序 usort( $users, function( $a, $b ) { return $b->latest_order_date - $a->latest_order_date; } );
总结
如果是生产环境且用户量较大,优先用方案一,数据库层面的关联查询效率高很多;小用户量的话方案二也能满足需求。
内容的提问来源于stack exchange,提问作者Madan
相关产品推荐
相关产品推荐

