1

I'm looking to use WooCommerce's add to cart validation to limit actions of a specific category.

I have two parent categories: Cat A and Cat B.

For Cat A, it should be unrestricted. So, it can be added to cart at any time.

For Cat B, I have different child categories. I'm looking to limit it so only one child category from Cat B can exist in the cart at any time. I'd like an error message to appear if someone tries to add a second Cat B child category product to cart when there's a conflicting child cat already in cart.

The child categories will be consistently changing, so querying by child cat ID isn't an option -- it has to be done through the parent. It's also an option to make all the Cat B child categories parent categories, but then I still need to exclude Cat A from the restrictions.

Based on Allow only one product per product category in cart answer code, this is what I have so far, trying to make it so the cart loop runs only if the product being added is not from Cat A:

add_filter( 'woocommerce_add_to_cart_validation', 'custom_checking_product_added_to_cart', 10, 3 );
function custom_checking_product_added_to_cart( $passed, $product_id, $quantity) {

    // Getting the product categories slugs in an array for the current product
    $product_cats_object = get_the_terms( $product_id, 'product_cat' );
    foreach($product_cats_object as $obj_prod_cat)
        $product_cats[] = $obj_prod_cat->slug;

    if ( ! $product_cats['cat-a-slug']) {
    
    // Iterating through each cart item
    foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item ){

        // When the product category of the current product does not match with a cart item
        if( ! has_term( $product_cats, 'product_cat', $cart_item['product_id'] ))
        {
            // Don't add 
            $passed = false;
            
            // Displaying a message
            wc_add_notice( 'Only one product from a category is allowed in cart', 'error' );

            // We stop the loop
            break;
        }
    }
    }
    return $passed;
}

This does what I want for the Cat B product but also limits Cat A, which I don't want.

While there are similar questions with solid answers to this, I haven't found one that solves my issue. I can't seem to get it to either ignore Cat A so it's unrestricted, or to read the child categories properly.

ximekil
  • 11
  • 2
  • Does this answer your question? [WooCommerce Cart - Conditional Items categories validation](https://stackoverflow.com/questions/38390058/woocommerce-cart-conditional-items-categories-validation) – Bhautik Apr 07 '21 at 19:35
  • It's close, but no. I will have multiple items in each Cat B child that need to be able to be added. I've updated my question with the code as I have it now. I think the cleanest way forward is to try to get it to loop through the cart only if the product being added is not in Cat A, but I can't seem to get it to work. – ximekil Apr 07 '21 at 19:42
  • Show us what you tried so far!. – Bhautik Apr 07 '21 at 19:43
  • Just added, took a sec to copy and paste! Thanks for your help =) – ximekil Apr 07 '21 at 19:44
  • The `Cat B` will be fixed? – Bhautik Apr 07 '21 at 19:49
  • Yes. Cat A and Cat B are fixed, Cat B children will be changing consistently. Alternative is to have Cat A be fixed and set all Cat B children as parent cats that are also changing consistently, so only fixed variable is Cat A. – ximekil Apr 07 '21 at 20:05
  • Ok i will be back. – Bhautik Apr 07 '21 at 20:08

1 Answers1

0

If your code according to the logic of category B, you can add this control to always allow the addition to the cart of products that belong to category A:

// if the product belongs to category A allows the addition of the product to the cart
if ( has_term( 'cat-a-slug', 'product_cat', $product_id ) ) {
    return $passed;
}

So the full function will be:

add_filter( 'woocommerce_add_to_cart_validation', 'custom_checking_product_added_to_cart', 10, 3 );
function custom_checking_product_added_to_cart( $passed, $product_id, $quantity) {

    // if the product belongs to category A allows the addition of the product to the cart
    if ( has_term( 'cat-a-slug', 'product_cat', $product_id ) ) {
        return $passed;
    }

    // Getting the product categories slugs in an array for the current product
    $product_cats_object = get_the_terms( $product_id, 'product_cat' );
    foreach ( $product_cats_object as $obj_prod_cat ) {
        $product_cats[] = $obj_prod_cat->slug;
    }

    // if the product belongs to category B
    if ( in_array( 'cat-b-slug', $product_cats ) ) {
        // Iterating through each cart item
        foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {

            // When the product category of the current product does not match with a cart item
            if ( ! has_term( $product_cats, 'product_cat', $cart_item['product_id'] ) ) {
                // Don't add 
                $passed = false;
                
                // Displaying a message
                wc_add_notice( 'Only one product from a category is allowed in cart', 'error' );

                // We stop the loop
                break;
            }
        }
    }

    return $passed;
}

I haven't tested the code but it should work. Add it to your active theme's functions.php.

Vincenzo Di Gaetano
  • 3,892
  • 3
  • 13
  • 32
  • This is close, but it doesn't allow me to add a product from Cat B if Cat A is already in the cart, or to add multiple items from the same Cat B child category... – ximekil Apr 08 '21 at 21:23