1

What I'm trying to do is to take the categories for products which are in the cart. Then check via some conditions what category id is and show different notice.

So far I have this

/**
* Cart collaterals hook.
*
* @hooked woocommerce_cross_sell_display
* @hooked woocommerce_cart_totals - 10
*/
$categories = array( 39 );

foreach ( WC()->cart->get_cart() as $cart_item ) {
    if ( has_term( $categories, 'product_cat', $cart_item['product_id'] ) ) {
        $found = true; // Set to true
        break; // Stop the loop
    }
}        

if( $found ) {
    echo 'Category with ID = 39';
}
else if ($found != $cart_item['category_ids']) {
    echo "Category with ID = 39 and other ID('s)";
}
else {
    "Category with ID != 39";
}

Seems like $cart_item['category_ids'] doesn't return categories. $found is working and showing category with ID = 39.

When I var_dump($cart_items) I do see different categories like this:

["category_ids"]=>
  array(1) {
    [0]=>
    int(39)
  }
   /// another stuff in the array

["category_ids"]=>
    array(2) {
      [0]=>
      int(32)
      [1]=>
      int(33)
    }

So, in cart I have products from categories with id 39, 32 and 33.

I've tried also WC()->cart->get_cart()->category_ids but this return NULL

UPDATE: This

$cat_ids = array();
foreach ( wc()->cart->get_cart() as $cart_item_key => $cart_item ) {
    $cat_ids = array_merge(
        $cat_ids, $cart_item['data']->get_category_ids()
    );
}

$cat_id = 39;
if ( in_array( $cat_id, $cat_ids ) ) {
    echo 'Only 39 ';
} elseif ( ! empty( $cat_ids ) ) {
    echo '39 + other';
} else {
    echo ' all other without 39';
}

Currently matching

When: category 39 + other -> Only 39

When: all other without 39 -> 39 + other

When: Only 39 -> Only 39

It should be

When: category 39 + other -> 39 + other

When: all other without 39 -> all other without 39

When: Only 39 -> Only 39

UPDATE

When: Category 39 + product from other category ( Category ID = 32, 33 etc )

var_dump(count( $cat_ids )); -> int(1)
var_dump($has_cat); -> bool(true)
var_dump(cat_ids); -> array(1) { [0]=> int(39) } <---- there are 3 products in the cart 2 of them are from other categories.

When: Category 39 only

var_dump(count( $cat_ids )); -> int(1)
var_dump($has_cat); -> bool(true)
var_dump(cat_ids); -> array(1) { [0]=> int(39) }

When: No category 39

var_dump(count( $cat_ids )); -> int(2)
var_dump($has_cat); -> bool(false)
var_dump(cat_ids); -> array(2) { [0]=> int(32) [1]=> int(33) } <--- product is added in 2 categories

UPDATE 2

Condition 1

1) cat 30; 
2) cat 39; 
$cond = 2 (because there are products in cart from 39 + other category)

Condition 2

1) cat 39; 
$cond = 1 (because in cart is/are product/s only from cat 39)

Condition 3

1) cat 40; 
2) cat 15;
$cond = last one (because there is no product/s from cat 39 in cart)
1
  • Please do not create long comment threads under an answer. Update your question with new insights instead. Thank you.
    – fuxia
    Commented Dec 11, 2018 at 10:16

2 Answers 2

2

Use $cart_item['data']->get_category_ids() to retrieve the category IDs:

$category_ids = $cart_item['data']->get_category_ids(); // array

The category_ids you see is not a direct item in the $cart_item array:

var_dump( $cart_item['category_ids'] ); // null and PHP throws a notice

It's an item in a protected property of the product data ($cart_item['data']) which is an object, or a class instance — e.g. the class is WC_Product_Simple for Simple products.

UPDATE

If you want to collect all the product category IDs, you can do it like so:

$cat_ids = array();
foreach ( wc()->cart->get_cart() as $cart_item_key => $cart_item ) {
    $cat_ids = array_merge(
        $cat_ids, $cart_item['data']->get_category_ids()
    );
}
var_dump( $cat_ids );

UPDATE #2

You can use this to check if a product in the cart is in certain categories:

$cat_ids = array( 39 );
foreach ( wc()->cart->get_cart() as $cart_item_key => $cart_item ) {
    if ( has_term( $cat_ids, 'product_cat', $cart_item['data'] ) ) {
        echo 'Has category 39<br>';
    } else {
        echo 'No category 39<br>';
    }
}

UPDATE #3/#4/#5

This should work as expected:

// Collect the category IDs.
$cat_ids = array();
foreach ( wc()->cart->get_cart() as $cart_item_key => $cart_item ) {
    $cat_ids = array_merge(
        $cat_ids, $cart_item['data']->get_category_ids()
    );
}

// And here we check the IDs.
$cat_id = 39;
$count = count( $cat_ids );
if ( 1 === $count && in_array( $cat_id, $cat_ids ) ) {
    echo 'Only in category 39';
} elseif ( $count && in_array( $cat_id, $cat_ids ) ) {
    echo 'In category 39 and other categories';
} else {
    echo 'No category 39';
}

Here's an alternate version of the if block above:

if ( $count && in_array( $cat_id, $cat_ids ) ) {
    // Only one category.
    if ( $count < 2 ) {
        echo 'Only in category 39';
    // Multiple categories.
    } else {
        echo 'In category 39 and other categories';
    }
} else {
    echo 'No category 39';
}
3
  • I've made already few tests and so far is looking good. Will do some more but I think this time is working! Thank you very much for the help!
    – S.I.
    Commented Dec 11, 2018 at 15:01
  • You're welcome! :) (And do let me know if it's still not working.)
    – Sally CJ
    Commented Dec 11, 2018 at 15:05
  • +1 from me cause your answer is exactly what I needed, but 1 thing to note here. Even though in the docs is clearly said 3rd param of has_term() is the post object or just the ID, in my case $cart_item['data'] did not work, but $cart_item['product_id'] or $cart_item['data']->get_id(). Maybe someone can clear this behavior ... Commented Dec 14, 2021 at 12:49
2

The answer from @sally works great, as long as your products are Simple products.

If your product uses a variation, then the above code no longer works as the $cart_item['data'] does not return the parent category for the variations.

This will allow you to get any products with variations - using the "product_id" to look up the "category id"

    $cat_id = '39'; // category to check against
    $cat_ids = [];
    foreach ( wc()->cart->get_cart() as $cart_item_key => $cart_item ) {
        $the_product = wc_get_product( $cart_item['product_id'] );
        $array_cat = $the_product->get_category_ids();
        if ( in_array($cat_id, $array_cat)) {
            array_push($cat_ids, $cat_id);
        }
        else {
            $cat_ids = array_merge($cat_ids, $array_cat);
        }    
    }

    // Count unique categories
    $count = count(array_unique($cat_ids));
    if ( ($count < 2) && ($cat_ids[0] == $cat_id)){
        echo 'only in category 39';
    }
    else {
        echo 'in category 39 and other';
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.