在 WooCommerce 中使特定产品互斥
Make specific products mutually exclusive in WooCommerce
情况
我的网站提供两种产品。如果用户购买产品 A,他们可以访问所有电子书。如果用户购买产品 B,他们将被允许选择一本电子书。在 WooCommerce 中,我创建了电子书作为产品 B 的变体。
产品 A ID = 477
产品 B ID = 297 (https://i.imgur.com/Sdo4XnT.png). While 297 is the main ID, I believe I should be using variation IDs eg. 1483, 997 (https://i.imgur.com/CEMFNLD.png)。
我正在尝试解决的问题
我希望这两种产品相互排斥。毕竟,如果用户购买了所有电子书(即产品 A)的访问权,那么他们就不需要购买产品 B 下的个别书籍。
最终结果
我尝试了一些代码(如下所示),但它根本不起作用。这意味着我仍然可以在同一个购物车中同时添加产品 A 和 B 的变体。
问题 1:我该如何解决?
问题 2: 是否有更简单的方法来不指定每个产品 B 变体?这是一个非常长的列表,从长远来看不是一个可扩展的解决方案。
我试过的
这似乎符合我的要求:
由于产品 B 的变化,我不得不稍微修改它。
add_action( 'woocommerce_add_to_cart', 'check_product_added_to_cart', 10, 6 );
function check_product_added_to_cart($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data) {
// Set HERE your targeted product ID
$target_product_ids1 = array(477);
$target_product_ids2 = array(1483, 997,998,999,1000,1001);
// Set HERE the product ID to remove
$item_id_to_remove1 = array(1483, 997,998,999,1000,1481);
$item_id_to_remove2 = array(477);
// Initialising some variables
$has_item1 = $has_item2 = $is_product_id1 = $is_product_id2 = false;
foreach( WC()->cart->get_cart() as $key => $item ){
// Check if the item to be removed 1 is in cart
if( in_array( $item['product_id'], $item_id_to_remove1) ){
$has_item1 = true;
$key_to_remove1 = $key;
}
// Check if the item to be removed 2 is in cart
if( in_array( $item['product_id'], $item_id_to_remove2) ){
$has_item2 = true;
$key_to_remove2 = $key;
}
// Check if we added to cart any targeted product IDs 1
if( in_array( $product_id, $target_product_ids1 ) ){
$is_product_id1 = true;
}
// Check if we added to cart any targeted product IDs 2
if( in_array( $product_id, $target_product_ids2 ) ){
$is_product_id2 = true;
}
}
if( $has_item1 && $is_product_id1 ){
WC()->cart->remove_cart_item($key_to_remove1);
// Optionaly displaying a notice for the removed item:
wc_add_notice( __( 'The product 1 "blab bla" has been removed from cart.', 'theme_domain' ), 'notice' );
}
if( $has_item2 && $is_product_id2 ){
WC()->cart->remove_cart_item($key_to_remove2);
// Optionaly displaying a notice for the removed item:
wc_add_notice( __( 'The product 2 "blab bla" has been removed from cart.', 'theme_domain' ), 'notice' );
}
}
有一种使用添加到购物车验证挂钩的更简单的方法:
add_filter( 'woocommerce_add_to_cart_validation', 'wc_add_to_cart_validation_filter_callback', 10, 3 );
function wc_add_to_cart_validation_filter_callback( $passed, $product_id, $quantity ) {
if( WC()->cart->is_empty() )
return $passed;
$product_id1 = 37; // Single product Id
$product_id2 = 19; // Variable product Id
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
if( ( $product_id = $product_id1 && $cart_item['product_id'] == $product_id2 )
|| ( $product_id = $product_id2 && $cart_item['product_id'] == $product_id1 ) ) {
wc_add_notice( sprintf(
__("This product can't not be purchased toggether with %s."),
'"<strong>' . $cart_item['data']->get_name() . '</strong>"'
), 'error' );
return false;
}
}
return $passed;
}
代码进入您的活动子主题(或活动主题)的 functions.php 文件。已测试并有效。
添加 (与您的评论相关):
另一种方法是当两种产品都在购物车中时静默删除第一项:
add_action('woocommerce_before_calculate_totals', 'keep_last_variation_from_variable_products', 10, 1 );
function keep_last_variation_from_variable_products( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$product_id1 = 37; // Single product Id
$product_id2 = 19; // Variable product Id
$product_ids = array($product_id1, $product_id2);
$items_keys = array();
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// If cart item matches with one of our defined product
if ( in_array( $cart_item['product_id'], $product_ids ) ) {
// Set the cart item key in an array (avoiding duplicates)
$items_keys[$cart_item['product_id']] = $cart_item_key;
}
}
// If both products are in cart just keep the last one silently
if( count($items_keys) > 1 ) {
$cart->remove_cart_item( reset($items_keys) ); // remove the first one
}
}
代码进入您的活动子主题(或活动主题)的 functions.php 文件。已测试并有效。
情况
我的网站提供两种产品。如果用户购买产品 A,他们可以访问所有电子书。如果用户购买产品 B,他们将被允许选择一本电子书。在 WooCommerce 中,我创建了电子书作为产品 B 的变体。
产品 A ID = 477
产品 B ID = 297 (https://i.imgur.com/Sdo4XnT.png). While 297 is the main ID, I believe I should be using variation IDs eg. 1483, 997 (https://i.imgur.com/CEMFNLD.png)。
我正在尝试解决的问题
我希望这两种产品相互排斥。毕竟,如果用户购买了所有电子书(即产品 A)的访问权,那么他们就不需要购买产品 B 下的个别书籍。
最终结果
我尝试了一些代码(如下所示),但它根本不起作用。这意味着我仍然可以在同一个购物车中同时添加产品 A 和 B 的变体。
问题 1:我该如何解决?
问题 2: 是否有更简单的方法来不指定每个产品 B 变体?这是一个非常长的列表,从长远来看不是一个可扩展的解决方案。
我试过的
这似乎符合我的要求:
由于产品 B 的变化,我不得不稍微修改它。
add_action( 'woocommerce_add_to_cart', 'check_product_added_to_cart', 10, 6 );
function check_product_added_to_cart($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data) {
// Set HERE your targeted product ID
$target_product_ids1 = array(477);
$target_product_ids2 = array(1483, 997,998,999,1000,1001);
// Set HERE the product ID to remove
$item_id_to_remove1 = array(1483, 997,998,999,1000,1481);
$item_id_to_remove2 = array(477);
// Initialising some variables
$has_item1 = $has_item2 = $is_product_id1 = $is_product_id2 = false;
foreach( WC()->cart->get_cart() as $key => $item ){
// Check if the item to be removed 1 is in cart
if( in_array( $item['product_id'], $item_id_to_remove1) ){
$has_item1 = true;
$key_to_remove1 = $key;
}
// Check if the item to be removed 2 is in cart
if( in_array( $item['product_id'], $item_id_to_remove2) ){
$has_item2 = true;
$key_to_remove2 = $key;
}
// Check if we added to cart any targeted product IDs 1
if( in_array( $product_id, $target_product_ids1 ) ){
$is_product_id1 = true;
}
// Check if we added to cart any targeted product IDs 2
if( in_array( $product_id, $target_product_ids2 ) ){
$is_product_id2 = true;
}
}
if( $has_item1 && $is_product_id1 ){
WC()->cart->remove_cart_item($key_to_remove1);
// Optionaly displaying a notice for the removed item:
wc_add_notice( __( 'The product 1 "blab bla" has been removed from cart.', 'theme_domain' ), 'notice' );
}
if( $has_item2 && $is_product_id2 ){
WC()->cart->remove_cart_item($key_to_remove2);
// Optionaly displaying a notice for the removed item:
wc_add_notice( __( 'The product 2 "blab bla" has been removed from cart.', 'theme_domain' ), 'notice' );
}
}
有一种使用添加到购物车验证挂钩的更简单的方法:
add_filter( 'woocommerce_add_to_cart_validation', 'wc_add_to_cart_validation_filter_callback', 10, 3 );
function wc_add_to_cart_validation_filter_callback( $passed, $product_id, $quantity ) {
if( WC()->cart->is_empty() )
return $passed;
$product_id1 = 37; // Single product Id
$product_id2 = 19; // Variable product Id
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
if( ( $product_id = $product_id1 && $cart_item['product_id'] == $product_id2 )
|| ( $product_id = $product_id2 && $cart_item['product_id'] == $product_id1 ) ) {
wc_add_notice( sprintf(
__("This product can't not be purchased toggether with %s."),
'"<strong>' . $cart_item['data']->get_name() . '</strong>"'
), 'error' );
return false;
}
}
return $passed;
}
代码进入您的活动子主题(或活动主题)的 functions.php 文件。已测试并有效。
添加 (与您的评论相关):
另一种方法是当两种产品都在购物车中时静默删除第一项:
add_action('woocommerce_before_calculate_totals', 'keep_last_variation_from_variable_products', 10, 1 );
function keep_last_variation_from_variable_products( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$product_id1 = 37; // Single product Id
$product_id2 = 19; // Variable product Id
$product_ids = array($product_id1, $product_id2);
$items_keys = array();
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// If cart item matches with one of our defined product
if ( in_array( $cart_item['product_id'], $product_ids ) ) {
// Set the cart item key in an array (avoiding duplicates)
$items_keys[$cart_item['product_id']] = $cart_item_key;
}
}
// If both products are in cart just keep the last one silently
if( count($items_keys) > 1 ) {
$cart->remove_cart_item( reset($items_keys) ); // remove the first one
}
}
代码进入您的活动子主题(或活动主题)的 functions.php 文件。已测试并有效。