Skip to content
Advertisement

Sum the quantities of products ordered by product categories from a WooCommerce order

I’m really stuck on this and I’d really appreciate any help with this.

The goal is to count the number of items in each category on a Woocommerce order so that each section can be headed by the category name and number of products. eg:

Burgers x 5

Below this will then be a list of all the burgers on that order.

Now I thought I had this working with this code:

$categories = [];
foreach ($order->get_items() as $item) {
  $product_id = $item['product_id'];
  $meta = $item['item_meta'];
  $meta = array_filter($meta, function ($key) {
                    return !in_array($key, Order::getHiddenKeys());
  }, ARRAY_FILTER_USE_KEY);
  $terms = get_the_terms($product_id, 'product_cat');
  $cat_id = $terms[0]->term_id;
  $categories[$cat_id][] = $item;
  $cat_name = $terms[0]->name;
}

foreach($categories as $category => $items){
?>
  <tr>
    <td colspan="3">
      <h4>
        <?php 
        if( $term = get_term_by( 'id', $category, 'product_cat' ) ){
          echo $term->name.' ('.$term->count.')';
          echo " &times; ";
          echo count($items);
        }
        ?>
      </h4>
    </td>
  </tr>
  <?php

But I’ve realised that this simply counts the number of products that have been ordered in that category, not the quantity. So if one of there was more than one of the same product, it would not count it. So for example, if the category contained these three items:

Cheeseburger x 2
Hamburger x 1

Would return two instead of three.

I’ve been looking through the categories and terms arrays but can’t seem to find anything that’s going to work. I’m sure I’m missing something but I’m just at a loss right now.

Can anyone point me in the right direction please?

(Also, if it’s of any use, this is an indirect follow on from a previous question Filtering the Woocommerce $order items By Category (Term))

Advertisement

Answer

You can do this in two ways:

  1. Adds up the quantities of the products ordered based on the product category obtained from the product (so it must be only 1)
  2. Set up a list of specific product categories for which you want to obtain a count of the quantities of products purchased

SOLUTION #1

You can use the get_the_terms() function to get the product category.

The function parameter must be the ID of the order to be counted.

Note that only the first product category returned by the get_the_terms() function will be checked. If a product has more than one you may have unexpected results.

// gets an array with the quantities of the ordered products grouped by product categories
function gets_the_quantities_of_products_ordered_grouped_by_product_categories( $order_id ) {

    // initializes the array that will contain the product categories with the ordered quantities of each
    $count_by_cat = array();

    // get the order object
    $order = wc_get_order( $order_id );

    // for each product ordered
    foreach ( $order->get_items() as $item ) {
        $product = $item->get_product();
        // get product categories
        $terms = get_the_terms( $product->get_id(), 'product_cat' );
        foreach ( $terms as $term ) {
            $cat_name = $term->name;
            // if the product category is already present in the array, add the quantities
            if ( array_key_exists( $cat_name, $count_by_cat ) ) {
                $count_by_cat[$cat_name] += $item->get_quantity();
            // otherwise it adds the category and quantity to the array
            } else {
                $count_by_cat[$cat_name] = $item->get_quantity();
            }
            break;
        }
    }

    return $count_by_cat;
}

SOLUTION #2

In this case you will have to initialize an array with the list of names of the product categories you want to get the number of products ordered.

With the has_term() function you can check if the product belongs to a specific product category.

The function parameter must be the ID of the order to be counted.

// gets an array with the quantities of the ordered products grouped by product categories
function gets_the_quantities_of_products_ordered_grouped_by_product_categories( $order_id ) {

    // initializes the array that will contain the product categories with the ordered quantities of each
    $count_by_cat = array();

    // set the product categories you want to get counts for
    $categories = array(
        'Clothes',
        'Shoes',
        'Pants',
        'Jackets',
        'Hats'
    );

    // get the order object
    $order = wc_get_order( $order_id );

    // for each product ordered
    foreach ( $order->get_items() as $item ) {
        $product = $item->get_product();
        // for each product category
        foreach ( $categories as $cat_name ) {
            // check if the product belongs to one of the product categories
            if ( has_term( $cat_name, 'product_cat', $product->get_id() ) ) {
                // if the product category is already present in the array, add the quantities
                if ( array_key_exists( $cat_name, $count_by_cat ) ) {
                    $count_by_cat[$cat_name] += $item->get_quantity();
                // otherwise it adds the category and quantity to the array
                } else {
                    $count_by_cat[$cat_name] = $item->get_quantity();
                }
                break;
            }
        }
    }

    return $count_by_cat;
}

Both functions will return an array similar to this:

$count_by_cat = array(
    'Shoes' => 4,
    'Pants' => 2,
    'Hats'  => 11
)

So you could print an HTML code similar to:

// print the counts for each product category
foreach ( $count_by_cat as $category_name => $count ) {
    echo "<p><strong>" . $category_name . ":</strong> " . $count . "</p>";
}

Both codes have been tested and work. Add them to your active theme’s functions.php.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement