Search code examples
phpwordpresswoocommercecartcustom-taxonomy

Check for Product Category in cart items with WooCommerce


I'm trying to make a condition, where a function displays on WooCommerce checkout page only, if any product from category ilutulestik is present in the shopping cart.

Currently, however, it does not seem to be able to obtain cart info. I assume that because, if I use if ( $cat_in_cart ) condition on a code, the function I use it on, does not display, even if I have a product from ilutulestik category present in the shopping cart.

I've tried many different methods to obtain cart info, but none have seemed to work. I'll include 2 ways of how I tried below:

Try 1

add_action('woocommerce_before_cart', 'kontrollime_ilutulestiku_olemasolu');

    function kontrollime_ilutulestiku_olemasolu()
    {

        global $woocommerce;
        $cat_in_cart = false;

            foreach ( WC()->cart->get_cart() as $cart_item_key => $values )
            {
            $item = $values['data'];
            $item_id = $item->id;

                if ( has_term( 'ilutulestik-2', 'product_cat', $item_id ) )
                {
                    $cat_in_cart = true;
                    break;
                }
            }
    }

Try 2

add_action('woocommerce_before_cart', 'kontrollime_ilutulestiku_olemasolu');

     function kontrollime_ilutulestiku_olemasolu($package)
     {

        global $woocommerce;
        $cat_in_cart = false;

            foreach ($package['contents'] as $product)
            {
                // get product categories
                $product_cats = wp_get_post_terms( 
$product['product_id'], 'product_cat', array('fields' => 'names') );
                // if it has category_name unset flat rate
                    if( in_array('ilutulestik-2', $product_cats) )
                    {
                    $cat_in_cart = true;
                    break;
                    }  
            }         
    }

I expect this piece of code to check if there is a product in cart that belongs to category Ilutulestik (or slug ilutulestik-2) and if it does, change $cat_in_cart value to true, so later I could activate any code with if ( $cat_in_cart ).


Solution

  • The correct way for cart items to be used with product categories is:

    add_action('woocommerce_before_cart', 'action_before_cart');
    function action_before_cart() {
        $categories   = array('ilutulestik-2');
        $has_category = false;
        
        // Loop through cart items
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            // Check for product categories
            if ( has_term( $categories, 'product_cat', $cart_item['product_id'] ) ) {
                $has_category = true;
                break;
            }
        }
        
        // Testing output (display a notice)
        if ( $has_category ) { 
            wc_print_notice( sprintf( 'Product category "%s" is in cart!', reset($categories)), 'notice' );
        }
    }
    

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


    If you need to check also for parent terms with product categories, you will use instead:

    // Custom conditional function that handle parent product categories too
    function has_product_categories( $categories, $product_id = 0 ) {
        $parent_term_ids = $categories_ids = array(); // Initializing
        $taxonomy        = 'product_cat';
        $product_id      = $product_id == 0 ? get_the_id() : $product_id;
    
        if( is_string( $categories ) ) {
            $categories = (array) $categories; // Convert string to array
        }
    
        // Convert categories term names and slugs to categories term ids
        foreach ( $categories as $category ){
            $result = (array) term_exists( $category, $taxonomy );
            if ( ! empty( $result ) ) {
                $categories_ids[] = reset($result);
            }
        }
    
        // Loop through the current product category terms to get only parent main category term
        foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
            if( $term->parent > 0 ){
                $parent_term_ids[] = $term->parent; // Set the parent product category
                $parent_term_ids[] = $term->term_id; // (and the child)
            } else {
                $parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
            }
        }
        return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
    }
    
    add_action('woocommerce_before_cart', 'action_before_cart');
    function action_before_cart() {
        $categories   = array('ilutulestik-2');
        $has_category = false;
    
        // Loop through cart items
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            // Check for product categories
            if ( has_product_categories( $cart_item['product_id'], $categories ) ) {
                $has_category = true;
                break;
            }
        }
    
        // Testing output (display a notice)
        if ( $has_category ) {
            wc_print_notice( sprintf( 'Product category "%s" is in cart!', reset($categories)), 'notice' );
        }
    }
    

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