简体   繁体   中英

Allow only one product category in cart at once in Woocommerce

How would I go about configuring the Woocommerce cart to only allow one product category type in it at a time?

The following code will allow adding to cart only items from one product category avoiding add to cart and displaying a custom notice:

add_filter( 'woocommerce_add_to_cart_validation', 'only_one_product_category_allowed', 20, 3 );
function only_one_product_category_allowed( $passed, $product_id, $quantity) {

    // Getting the product categories term slugs in an array for the current product
    $term_slugs   = wp_get_post_terms( $product_id, 'product_cat', array('fields' => 'slugs') );

    // Loop through cart items
    foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item ){

        // Check if the product category of the current product don't match with a cart item
        if( ! has_term( $term_slugs, 'product_cat', $cart_item['product_id'] ) ){

            // Displaying a custom notice
            wc_add_notice( __('Only items from one product category are allowed in cart'), 'error' );

            // Avoid add to cart
            return false; // exit
        }
    }
    return $passed;
}

Code goes in function.php file of the active child theme (or active theme). Tested and works.


Addition (updated) - The same but only for parent product categories :

add_filter( 'woocommerce_add_to_cart_validation', 'only_one_product_category_allowed', 20, 3 );
function only_one_product_category_allowed( $passed, $product_id, $quantity) {
    $parent_term_ids = $item_parent_term_ids = array(); // Initializing

    // Loop through the current product category terms to get only parent main category term
    foreach( get_the_terms( $product_id, 'product_cat' ) as $term ){
        if( $term->parent > 0 ){
            $parent_term_ids[] = $term->parent; // Set the parent product category
        }
    }

    // Loop through cart items
    foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item ){
        // Loop through the cart item product category terms to get only parent main category term
        foreach( get_the_terms( $cart_item['product_id'], 'product_cat' ) as $term ){
            if( $term->parent > 0 ){
                $item_parent_term_ids[] = $term->parent; // Set the parent product category
            }
        }

        // Check if parent product categories don't match
        if( ! array_intersect( $parent_term_ids, $item_parent_term_ids ) ){

            // Displaying a custom notice
            wc_add_notice( __('Only items from one product category are allowed in cart'), 'error' );

            // Avoid add to cart
            return false; // exit
        }
    }
    return $passed;
}

Code goes in function.php file of the active child theme (or active theme). Tested and works.

@LoicTheAztec Pls what if i want to allow just products within a certain category to be added to be added at checkout. My case is, i have some bookable products and physical products and they both have different shipping fees. So i want a case where if someone orders a Bookable product they wont be able to add any physical product to cart unless they do that on a separate order. Thanks

Thanks LoicTheAztec for providing the great answer!
However, the parent product categories version does not fit to my case.
LoicTheAztec 's version returns false when the products's category does not have parent, even those products have the same category.
Here's the modification of it to handle the above case.

add_filter( 'woocommerce_add_to_cart_validation', 'only_one_product_category_allowed', 20, 3 );
function only_one_product_category_allowed( $passed, $product_id, $quantity) {
    $parent_term_ids = $item_parent_term_ids = array(); // Initializing

    // Loop through the current product category terms to get the parent main category term if any.
    // Otherwise we get the current product's own category.
    foreach( get_the_terms( $product_id, 'product_cat' ) as $term ){
        if ( $term->parent > 0 ){
            $parent_term_ids[] = $term->parent; // Set the parent product category
        } else {
            $parent_term_ids[] = $term->term_id; // Set the category itself of the current product for later comparison
        }
    }

    // Loop through cart items
    foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item ){
        // Loop through the cart item product category terms to get the parent main category term if any.
        // Otherwise we get the cart item's own category.
        foreach( get_the_terms( $cart_item['product_id'], 'product_cat' ) as $term ){
            if ( $term->parent > 0 ){
                $item_parent_term_ids[] = $term->parent; // Set the parent product category
            } else {
                $item_parent_term_ids[] = $term->term_id; // Set the category itself of the cart item for later comparison
            }
        }

        // Check if parent product categories don't match
        if( ! array_intersect( $parent_term_ids, $item_parent_term_ids ) ){

            // Displaying a custom notice
            wc_add_notice( __('Only items from one product category are allowed in cart'), 'error' );

            // Avoid add to cart
            return false; // exit
        }
    }
    return $passed;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM