允许客户仅购买定义的 WooCommerce 产品类别中的一种产品

发布于 2025-01-11 12:00:57 字数 811 浏览 2 评论 0原文

我想让客户只购买指定类别中的一种产品。所有产品的价格均为 0(零)。仅收取送货费。

我参考了相同的场景并尝试了这段代码。但对于未登录的用户,此代码会失败。当我尝试多次购买时,我就没有购买的想法。想要在第一次成功尝试购买后进行限制。我正在使用子主题 functions.php 文件。

注意:客户在购买前无需在网站上注册。

add_filter('woocommerce_add_to_cart_validation','filter_add_to_cart_validation',20, 2);
function filter_add_to_cart_validation($valid, $product_id){
    $current_user = wp_get_current_user();
    if ( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id) && has_term( array('free-giveaway'), 'product_cat', $product_id ) ) {
        wc_add_notice( __( 'You already bought an item. Let others to buy as well.', 'woocommerce' ), 'error' );
        $valid = false;
    }
    return $valid;
}

I want to let customers buy only one product from a defined category. All products are priced as 0 (zero). Only delivery fee is charged.

I referred to the same scenario and tried this code. But this code fails for not logged in users. When I try multiple purchases I have no matter of buying. Want to limit after the first successful attempt of a purchase. I am using the child theme functions.php file.

Note: customers do not need to register in the website before doing a purchase.

add_filter('woocommerce_add_to_cart_validation','filter_add_to_cart_validation',20, 2);
function filter_add_to_cart_validation($valid, $product_id){
    $current_user = wp_get_current_user();
    if ( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id) && has_term( array('free-giveaway'), 'product_cat', $product_id ) ) {
        wc_add_notice( __( 'You already bought an item. Let others to buy as well.', 'woocommerce' ), 'error' );
        $valid = false;
    }
    return $valid;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

何止钟意 2025-01-18 12:00:57

与答案相关的解释/评论:

所以您得到:

function filter_woocommerce_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = null, $variations = null ) {
    // Set (multiple) categories
    $categories = array ( 'free-giveaway', 'categorie-1' );
    
    // If passed & has category
    if ( $passed && has_term( $categories, 'product_cat', $product_id ) ) {
        // Initialize
        $value = '';

        // User logged in
        if ( is_user_logged_in() ) {
            // Get the current user's ID 
            $value = get_current_user_id();
        } else {
            // Get billing_email
            $value = WC()->customer->get_billing_email();

            // When empty
            if ( empty ( $value ) ) {
                // Get account email
                $value = WC()->customer->get_email();   
            }
        }

        // NOT empty
        if ( ! empty ( $value ) ) {
            if ( has_bought( $value ) ) {
                // Display an error message
                wc_add_notice( __( 'My custom error message', 'woocommerce' ), 'error' );

                // False
                $passed = false;
            }
        }       
    }

    return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'filter_woocommerce_add_to_cart_validation', 10, 5 );

// Based partially on wc_customer_bought_product(), will return a boolean value based on orders count (false for O orders and true when there is at least one paid order)
function has_bought( $value = 0 ) {
    if ( ! is_user_logged_in() && $value === 0 ) {
        return false;
    }

    global $wpdb;
    
    // Based on user ID (registered users)
    if ( is_numeric( $value ) ) { 
        $meta_key   = '_customer_user';
        $meta_value = $value == 0 ? (int) get_current_user_id() : (int) $value;
    } 
    // Based on billing email (Guest users)
    else { 
        $meta_key   = '_billing_email';
        $meta_value = sanitize_email( $value );
    }
    
    $paid_order_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    $count = $wpdb->get_var( $wpdb->prepare("
        SELECT COUNT(p.ID) FROM {$wpdb->prefix}posts AS p
        INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $paid_order_statuses ) . "' )
        AND p.post_type LIKE 'shop_order'
        AND pm.meta_key = '%s'
        AND pm.meta_value = %s
        LIMIT 1
    ", $meta_key, $meta_value ) );

    // Return a boolean value based on orders count
    return $count > 0;
}

Explanation/comments related to the answer:

  • The has_term() WordPress function is used to check the product category
  • It is better to only apply these kinds of checks (has bought before) for logged in users, since usually no data is known from customers. However, it is possible that you can obtain the e-mail address via WC_Customer. (this will not always suffice, hence my comment to only apply this to logged in users)
  • Note: the has_bought() function is copied and pasted from Checking if customer has already bought something in WooCommerce answer code

So you get:

function filter_woocommerce_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = null, $variations = null ) {
    // Set (multiple) categories
    $categories = array ( 'free-giveaway', 'categorie-1' );
    
    // If passed & has category
    if ( $passed && has_term( $categories, 'product_cat', $product_id ) ) {
        // Initialize
        $value = '';

        // User logged in
        if ( is_user_logged_in() ) {
            // Get the current user's ID 
            $value = get_current_user_id();
        } else {
            // Get billing_email
            $value = WC()->customer->get_billing_email();

            // When empty
            if ( empty ( $value ) ) {
                // Get account email
                $value = WC()->customer->get_email();   
            }
        }

        // NOT empty
        if ( ! empty ( $value ) ) {
            if ( has_bought( $value ) ) {
                // Display an error message
                wc_add_notice( __( 'My custom error message', 'woocommerce' ), 'error' );

                // False
                $passed = false;
            }
        }       
    }

    return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'filter_woocommerce_add_to_cart_validation', 10, 5 );

// Based partially on wc_customer_bought_product(), will return a boolean value based on orders count (false for O orders and true when there is at least one paid order)
function has_bought( $value = 0 ) {
    if ( ! is_user_logged_in() && $value === 0 ) {
        return false;
    }

    global $wpdb;
    
    // Based on user ID (registered users)
    if ( is_numeric( $value ) ) { 
        $meta_key   = '_customer_user';
        $meta_value = $value == 0 ? (int) get_current_user_id() : (int) $value;
    } 
    // Based on billing email (Guest users)
    else { 
        $meta_key   = '_billing_email';
        $meta_value = sanitize_email( $value );
    }
    
    $paid_order_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    $count = $wpdb->get_var( $wpdb->prepare("
        SELECT COUNT(p.ID) FROM {$wpdb->prefix}posts AS p
        INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $paid_order_statuses ) . "' )
        AND p.post_type LIKE 'shop_order'
        AND pm.meta_key = '%s'
        AND pm.meta_value = %s
        LIMIT 1
    ", $meta_key, $meta_value ) );

    // Return a boolean value based on orders count
    return $count > 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文