WooCommerce:限制用户指定时间内购2件商品并调整错误提示位置
WooCommerce 实现指定类别商品限时限购2件(仅购物车页提示)
需求说明
- 为指定商品类别设置限购规则:用户在指定时间范围内最多可购买2件该类别商品(包含已支付订单和当前购物车中的数量)
- 允许商品正常加入购物车,仅在购物车页面展示限购错误提示
完整实现代码
// 计算用户在指定时间内已购买的指定类别商品总数量 function get_user_purchased_category_qty( $category_slugs, $time_range_days = 1 ) { if ( ! is_user_logged_in() && empty( WC()->customer->get_billing_email() ) ) { return 0; } global $wpdb; $time_threshold = strtotime( "-{$time_range_days} days" ); // 识别用户:登录用户用ID,访客用邮箱 if ( is_user_logged_in() ) { $meta_key = '_customer_user'; $meta_value = get_current_user_id(); } else { $meta_key = '_billing_email'; $meta_value = sanitize_email( WC()->customer->get_billing_email() ); } $paid_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() ); $statuses_in = "'wc-" . implode( "','wc-", $paid_statuses ) . "'"; // 查询已购买的指定类别商品数量 $purchased_qty = $wpdb->get_var( $wpdb->prepare( " SELECT SUM(oi.quantity) FROM {$wpdb->prefix}posts p INNER JOIN {$wpdb->prefix}postmeta pm ON p.ID = pm.post_id INNER JOIN {$wpdb->prefix}woocommerce_order_items oi ON p.ID = oi.order_id INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim ON oi.order_item_id = oim.order_item_id INNER JOIN {$wpdb->prefix}term_relationships tr ON oim.meta_value = tr.object_id INNER JOIN {$wpdb->prefix}term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN {$wpdb->prefix}terms t ON tt.term_id = t.term_id WHERE p.post_status IN ({$statuses_in}) AND p.post_type = 'shop_order' AND pm.meta_key = %s AND pm.meta_value = %s AND p.post_date >= %s AND oim.meta_key = '_product_id' AND tt.taxonomy = 'product_cat' AND t.slug IN ('" . implode( "','", array_map( 'esc_sql', $category_slugs ) ) . "') ", $meta_key, $meta_value, date( 'Y-m-d H:i:s', $time_threshold ) ) ); return empty( $purchased_qty ) ? 0 : (int)$purchased_qty; } // 计算购物车中指定类别商品的数量 function get_cart_category_qty( $category_slugs ) { $cart_qty = 0; foreach ( WC()->cart->get_cart() as $cart_item ) { if ( has_term( $category_slugs, 'product_cat', $cart_item['product_id'] ) ) { $cart_qty += $cart_item['quantity']; } } return $cart_qty; } // 在购物车页面检查限购规则并显示提示 function check_category_limit_on_cart() { if ( ! is_cart() ) return; // 配置参数:指定类别slug、限购数量、时间范围(天) $target_categories = array( 'kitchen' ); $max_allowed = 2; $time_range = 1; // 1天内 $purchased_qty = get_user_purchased_category_qty( $target_categories, $time_range ); $cart_qty = get_cart_category_qty( $target_categories ); $total_qty = $purchased_qty + $cart_qty; if ( $total_qty > $max_allowed ) { wc_add_notice( sprintf( '您在%s天内最多可购买%d件该类别商品,当前已选购%d件', $time_range, $max_allowed, $total_qty ), 'error' ); // 可选:阻止结账按钮(如果需要) // add_filter( 'woocommerce_proceed_to_checkout_button', '__return_false' ); } } add_action( 'woocommerce_before_cart', 'check_category_limit_on_cart' ); // 可选:在结账页面也检查(防止用户直接跳转结账) function check_category_limit_on_checkout() { if ( ! is_checkout() || is_wc_endpoint_url( 'order-received' ) ) return; $target_categories = array( 'kitchen' ); $max_allowed = 2; $time_range = 1; $purchased_qty = get_user_purchased_category_qty( $target_categories, $time_range ); $cart_qty = get_cart_category_qty( $target_categories ); $total_qty = $purchased_qty + $cart_qty; if ( $total_qty > $max_allowed ) { wc_add_notice( sprintf( '您在%s天内最多可购买%d件该类别商品,当前已选购%d件', $time_range, $max_allowed, $total_qty ), 'error' ); } } add_action( 'woocommerce_before_checkout_form', 'check_category_limit_on_checkout' );
代码关键说明
数量统计逻辑
get_user_purchased_category_qty:查询用户在指定时间内已支付订单中指定类别的商品总数量,支持登录用户(用ID识别)和访客(用账单邮箱识别)get_cart_category_qty:统计当前购物车中指定类别的商品数量
提示触发时机
- 在
woocommerce_before_cart钩子中检查,仅在购物车页面显示错误提示,不拦截商品加入购物车的操作 - 可选添加结账页面检查,防止用户绕过购物车直接结账
- 在
可配置参数
- 修改
$target_categories数组设置需要限购的商品类别slug - 修改
$max_allowed设置限购数量 - 修改
$time_range设置时间范围(单位:天)
- 修改
内容的提问来源于stack exchange,提问作者jamesnelson82
相关产品推荐
相关产品推荐

