如果在 Woocommerce 中购买了特定产品类别中的任何商品,则将产品设置为仅购买一次或不购买
Make a product to be purchased only once or not if any item from a specific product category has been purchased in Woocommerce
在 woocommerce 中,我只使用简单的产品,我有一个来自产品类别 "A" 的特殊产品 "free trial package",我愿意:
- 让客户只购买这个"free trial package"一次 …
- 如果客户首先购买了同一产品类别的其他产品"A",那么客户将无法再购买此"free trial package"
这意味着客户只有在首次购买该产品类别 "A" 时才能获得 "free trial package"。
我的代码似乎没有正常工作,它只做了第一点。
另一个问题是,如果用户订单完成,下次用户打开购物车时会显示一条奇怪的消息:
"you cant select this product anymore, you already bought this package"。好像是 Woocommerce 缓存问题什么的…
到目前为止,这是我的代码:
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 );
感谢任何帮助。
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 );
更新 2
根据 "" 答案代码,以下将阻止购买 "trial package" 产品,如果它已经购买过一次,或者如果已购买定义产品类别 "A" 的任何产品。
您的实际代码自 Woocommerce 3 以来已过时,并且存在一些错误……
我使用受 wc_customer_bought_product()
source code 启发的自定义条件函数来检查客户是否可以购买 "free trial" 产品。此函数还将检查产品 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 文件。已测试并有效。
要处理产品类别 Term ID 而不是 Term Slug,请改用以下条件函数:
// 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;
}
对于有特殊字符的外语来说是更好的选择。
在 woocommerce 中,我只使用简单的产品,我有一个来自产品类别 "A" 的特殊产品 "free trial package",我愿意:
- 让客户只购买这个"free trial package"一次 …
- 如果客户首先购买了同一产品类别的其他产品"A",那么客户将无法再购买此"free trial package"
这意味着客户只有在首次购买该产品类别 "A" 时才能获得 "free trial package"。
我的代码似乎没有正常工作,它只做了第一点。
另一个问题是,如果用户订单完成,下次用户打开购物车时会显示一条奇怪的消息: "you cant select this product anymore, you already bought this package"。好像是 Woocommerce 缓存问题什么的…
到目前为止,这是我的代码:
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 );
感谢任何帮助。
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 );
更新 2
根据 "
您的实际代码自 Woocommerce 3 以来已过时,并且存在一些错误……
我使用受 wc_customer_bought_product()
source code 启发的自定义条件函数来检查客户是否可以购买 "free trial" 产品。此函数还将检查产品 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 文件。已测试并有效。
要处理产品类别 Term ID 而不是 Term Slug,请改用以下条件函数:
// 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;
}
对于有特殊字符的外语来说是更好的选择。