在 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 文件。已测试并有效。