Php 如果某一特定产品类别中的任何项目已在Woocommerce中购买,则仅购买一次产品或不购买

Php 如果某一特定产品类别中的任何项目已在Woocommerce中购买,则仅购买一次产品或不购买,php,wordpress,woocommerce,cart,checkout,Php,Wordpress,Woocommerce,Cart,Checkout,在woocommerce中,我只使用简单的产品,我有一个来自产品类别“a”的特殊产品“免费试用包”,我愿意: 让客户只购买一次此“免费试用套餐” 如果客户先购买同一产品类别“A”的其他产品,则客户无法再购买此“免费试用包” 这意味着客户只有在首次购买该产品类别“A”时才能获得“免费试用包” 我的代码似乎工作不正常,它只做了第一点 另一个问题是,如果用户订单完成,下次用户打开购物车时会显示一条奇怪的消息: “你不能再选择这个产品了,你已经买了这个软件包。”这就像是电子商务缓存问题或其他什么 以下是

在woocommerce中,我只使用简单的产品,我有一个来自产品类别“a”的特殊产品“免费试用包”,我愿意:

  • 让客户只购买一次此“免费试用套餐”
  • 如果客户先购买同一产品类别“A”的其他产品,则客户无法再购买此“免费试用包”
  • 这意味着客户只有在首次购买该产品类别“A”时才能获得“免费试用包”

    我的代码似乎工作不正常,它只做了第一点

    另一个问题是,如果用户订单完成,下次用户打开购物车时会显示一条奇怪的消息: “你不能再选择这个产品了,你已经买了这个软件包。”这就像是电子商务缓存问题或其他什么

    以下是我目前的代码:

    function sv_disable_repeat_purchase( $purchasable, $product ) {
        $non_purchasable = 190;
    
        $product_id = $product->is_type( 'variation' ) ? $product->variation_id : $product->id;
    
        if ( $product_id != $non_purchasable ) {
            $purchasable = true;
        }
    
        if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $product_id ) ) {
            $purchasable = false;
        }
    
        if ( $purchasable && $product->is_type( 'variation' ) ) {
            $purchasable = $product->parent->is_purchasable();
        }
    
        return $purchasable;
    }
    add_filter( 'woocommerce_variation_is_purchasable', 'sv_disable_repeat_purchase', 10, 2 );
    add_filter( 'woocommerce_is_purchasable', 'sv_disable_repeat_purchase', 10, 2 );
    

    非常感谢您的帮助。

    更新2

    function wc_customer_purchased_product_in_cat( $product ) {
    
        // enter the category for which a single purchase is allowed
        $non_repeatable = 'ADD YOUR CATEGORY HERE';
    
        // bail if this product is in not in our target category
        if ( ! has_term( $non_repeatable, 'product_cat', $product->get_id() ) ) {
            return false;
        }
    
        // the product has our target category, so return whether the customer purchased
        return wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $product->get_id() );
    }
    
    function wc_disable_repeat_purchase( $purchasable, $product ) {
    
        if ( wc_customer_purchased_product_in_cat( $product ) ) {
            $purchasable = false;
        }
    
        // double-check for variations: if parent is not purchasable, then variation is not
        if ( $purchasable && $product->is_type( 'variation' ) ) {
            $purchasable = $product->parent->is_purchasable();
        }
    
        return $purchasable;
    }
    add_filter( 'woocommerce_variation_is_purchasable', 'wc_disable_repeat_purchase', 10, 2 );
    add_filter( 'woocommerce_is_purchasable', 'wc_disable_repeat_purchase', 10, 2 );
    
    根据“”回答代码,如果“试用包”产品已经购买过一次,或者定义的“a”类产品的任何产品已经购买过,则以下内容将阻止从该产品购买

    您的实际代码从Woocommerce 3开始就过时了,并且出现了一些错误

    我使用一个定制的条件函数来检查客户是否可以购买“免费试用”产品。此功能还将检查产品ID或产品类别:

    function has_bought_items( $user_id = 0, $product_ids = 0, $categories_slugs = '' ) {
        global $wpdb;
        $customer_id = $user_id == 0 || $user_id == '' ? get_current_user_id() : $user_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 || '' ) ) {
            $query_in = "IN ($product_ids)";
        }
        else {
            $categories = is_array( $categories_slugs ) ? implode("','", $categories_slugs) : $categories_slugs;
    
            $query_in = "IN (
            SELECT DISTINCT products.ID  FROM {$wpdb->prefix}posts AS products
            INNER JOIN {$wpdb->prefix}term_relationships as term_rel
                ON products.ID = term_rel.object_id
            INNER JOIN {$wpdb->prefix}term_taxonomy as term_tax
                ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
            INNER JOIN {$wpdb->prefix}terms as terms
                ON term_tax.term_taxonomy_id = terms.term_id
            WHERE products.post_status = 'publish'
            AND term_tax.taxonomy = 'product_cat'
            AND terms.slug IN ('$categories')
            )";
        }
    
        // Count the number of products
        $product_count_query = $wpdb->get_var( "
            SELECT DISTINCT COUNT(orders.ID)
            FROM {$wpdb->prefix}posts AS orders
            INNER JOIN {$wpdb->prefix}postmeta AS order_meta
                ON orders.ID = order_meta.post_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items
                ON orders.ID = order_items.order_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
                ON order_items.order_item_id = order_itemmeta.order_item_id
            WHERE orders.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
            AND order_meta.meta_key = '_customer_user'
            AND order_meta.meta_value = $customer_id
            AND order_itemmeta.meta_key IN ( '_product_id', '_variation_id' )
            AND order_itemmeta.meta_value $query_in
        " );
    
        // Return a boolean value if count is higher than 0
        return $product_count_query > 0 ? true : false;
    }
    
    使用上述自定义条件函数重新访问的代码:

    // add_filter( 'woocommerce_variation_is_purchasable', 'trial_package_purchasable_once', 10, 2 );
    add_filter( 'woocommerce_is_purchasable', 'trial_package_purchasable_once', 10, 2 );
    function trial_package_purchasable_once( $purchasable, $product ) {
        // HERE set the free trial product Id to be purchased only once (can be an array of Ids too)
        $free_trial_id = 50;
    
        // HERE set the specific product category SLUG (could be an array of slugs too)
        $categories = array('lettering'); // Only slug terms
    
            if ( $product->get_id() == $free_trial_id ) {
                // Check if any item of the specific product category has already been purchased once
                if ( has_bought_items( get_current_user_id(), '', $categories ) ) {
                    return false;
                }
                // Check if the free trial product has already been purchased once
                elseif ( has_bought_items( get_current_user_id(), $free_trial_id ) ) {
                    return false;
                }
            }
        }
    
        return $purchasable;
    }
    
    代码进入活动子主题(或活动主题)的function.php文件。测试和工作


    要处理产品类别术语ID而不是术语段塞,请改用以下条件函数:

    // For Product category(ies) Id(s)
    function has_bought_items( $user_id = 0, $product_ids = 0, $categories_ids = '' ) {
        global $wpdb;
        $customer_id = $user_id == 0 || $user_id == '' ? get_current_user_id() : $user_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 || '' ) ) {
            $query_in = "IN ($product_ids)";
        }
        else {
            $categories = is_array( $categories_ids ) ? implode(',', $categories_ids) : $categories_ids;
    
            $query_in = "IN (
            SELECT DISTINCT products.ID  FROM {$wpdb->prefix}posts AS products
            INNER JOIN {$wpdb->prefix}term_relationships as term_rel
                ON products.ID = term_rel.object_id
            INNER JOIN {$wpdb->prefix}term_taxonomy as term_tax
                ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
            INNER JOIN {$wpdb->prefix}terms as terms
                ON term_tax.term_taxonomy_id = terms.term_id
            WHERE products.post_status = 'publish'
            AND term_tax.taxonomy = 'product_cat'
            AND terms.term_id IN ($categories)
            )";
        }
    
        // Count the number of products
        $product_count_query = $wpdb->get_var( "
            SELECT DISTINCT COUNT(orders.ID)
            FROM {$wpdb->prefix}posts AS orders
            INNER JOIN {$wpdb->prefix}postmeta AS order_meta
                ON orders.ID = order_meta.post_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items
                ON orders.ID = order_items.order_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
                ON order_items.order_item_id = order_itemmeta.order_item_id
            WHERE orders.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
            AND order_meta.meta_key = '_customer_user'
            AND order_meta.meta_value = $customer_id
            AND order_itemmeta.meta_key IN ( '_product_id', '_variation_id' )
            AND order_itemmeta.meta_value $query_in
        " );
    
        // Return a boolean value if count is higher than 0
        return $product_count_query > 0 ? true : false;
    }
    

    对于带有特殊字符的外语来说,这是更好的选择。

    产品id在哪里?!它不起作用,我先买了20美元的套餐,然后我试着买了免费套餐,我做到了!它实际上是这样做的,它让你买任何东西,只要你买了免费的包装,你就不能买任何东西!我想要的是,只有当你订购免费套餐作为开始购买时,你才可以购买它,但如果你这样做了,你就不能再购买它,如果你购买免费套餐以外的任何东西,你就不能再次选择免费套餐当我购买免费套餐时,它不仅不会让我从同一个类别购买,而且也不会让我再次购买!“添加到购物车”按钮在所有内容上完全消失!嗯,代码似乎需要在每个ifOn的第一个函数中以某种形式返回替换
    和terms.slug in($categories)
    by
    和terms.name in($categories)
    …或在最后一个函数
    和terms.term\u id in($categories)
    中替换
    和terms.name in($categories)