WooCommerce Tips & Tricks – Get all the categories to which a product belongs
As active contributors of several communities, such as the Advanced WooCommerce and WooCommerce Help & Share groups on Facebook, we came across a question that seem to be quite frequent.
How to get all of a product’s categories
This operation is simple, it just requires a bit more work than one would expect. It’s very easy to fetch the categories to which a product is assigned directly, but a product may also belong to parent categories (a parent category is a category to which a subcategory belongs). The screenshot below explains the concept.
In the above example, the product belongs to the following categories:
- Directly to Subcategory A1 and Some other category, as it’s assigned directly to them.
- Indirectly to Category A, which is the parent of Subcategory A1.
Now that the concepts are clear, let’s get coding.
Step 1 – Get the direct categories of a product
This is the easiest part. It’s just a matter to find all the “category” terms associated to a product. Our function will look like this:
function aelia_get_product_categories($product, $return_raw_categories = false) { $result = array(); // Get all the categories to which a product is assigned $categories = wp_get_post_terms($product->id, 'product_cat'); // The $categories array contains a list of objects. Most likely, we would // like to have categorys slug as a keys, and their names as values. The# // wp_list_pluck() function is perfect for this $categories = wp_list_pluck($categories, 'name', 'slug'); return $categories; }
The result of this function, once applied to our example product, will be the following:
array( 'subcategory-a1' => 'Subcategory A1', 'some-other-category' => 'Some other category', )
All good, we have the categories to which the product is assigned directly. Now we need to get all the parent categories.
Step 2 – Get the parent category (or categories) of a given category
To keep things tidy, we will create a second function to get the parent categories of a category. This requires a similar approach to the one used for the products.
function aelia_get_parent_categories($category_id) { $parent_categories = array(); // This will retrieve the IDs of all the parent categories // of a category, all the way to the top level $parent_categories_ids = get_ancestors($category_id, 'product_cat'); foreach($parent_categories_ids as $category_id) { // Now we retrieve the details of each category, using its // ID, and extract its name $category = get_term_by('id', $category_id, 'product_cat'); $parent_categories[$category->slug] = $category->name; } return $parent_categories; }
The above will return the following result for Subcategory A1:
array( 'category-a' => 'Category A' )
As before, we have a list with category slugs as keys, and category names as values. Time to finish the job.
Step 3 – Putting the pieces together
Now that we can get both the direct categories of a product and their parent categories, we can alter the first function to call the second and give us a result that includes all the categories. The modified function will look as follows:
function aelia_get_product_categories($product, $return_raw_categories = false) { $result = array(); $categories = wp_get_post_terms($product->id, 'product_cat'); if(is_array($categories) && !$return_raw_categories) { $parent_categories = array(); // Retrieve the parent categories of each category to which // the product is assigned directly foreach($categories as $category) { // Using array_merge(), we keep a list of parent categories // that doesn't include duplicates $parent_categories = array_merge($parent_categories, aelia_get_parent_categories($category->term_id)); } // When we have the full list of parent categories, we can merge it with // the list of the product's direct categories, producing a single list $categories = array_merge($parent_categories, wp_list_pluck($categories, 'name', 'slug')); } return $categories; }
As you will probably have guessed, the new function will return the following result:
array( 'subcategory-a1' => 'Subcategory A1', 'some-other-category' => 'Some other category', 'category-a' => 'Category A', )
That is, a list of all the direct and indirect categories to which a product belongs. Mission accomplished!
For your convenience, you can find the complete code here: WooCommerce – WooCommerce – Get product categories, including parent categories (Pastebin).
Need help?
Should you need help implementing the solution, or if you would need to have the category search functions implemented as part of a more complex custom project, please feel free to contact us. We will review your specifications and give you a quote for your customisation.
The Aelia Team
Hey, cant seem to recieve any but an empty array with that function.
I do call this function from the product page.
If you copied the code from the article text, I would suggest to use the one from the Pastebin you find at the end of the article instead (http://pastebin.com/pnrinKWd). That code works fine on WooCommerce 2.6 (just checked).
I tried out your code, but it appears the parent category (not ticked) cannot be found when the child category is ticked for the product. The categories selection is identical to the above example.
[ ] Add-Ons
[x] Wine & Liquor
The “Wine & Liquor” category indirectly belongs to the “Add-Ons” category.
Unfortunately, I see “Categories: Wine & Liquor” on the product page, and not “Categories: Add-Ons, Wine & Liquor”
What is amiss?
Please advise. Thank you.
Hi Jason,
We reviewed the code, and it still works fine. You will have to ensure that “Wine and Liquor” is a child category of “Add-Ons” (see example: https://prnt.sc/i8oken). If they are at the same level, then they will be considered independent from each other.
I’ve submitted a reply about a week ago. Why hasn’t it been added here?
We haven’t received a reply. Perhaps it was blocked by an antispam filter by mistake. I would suggest to use our contact form, your message will reach us directly.
I left this alone for a long time, and I decided to return to it. Anyway, I’m curious if your custom snippet goes into “/woocommerce/templates/single-product/meta.php”. And what other line(s) of code need to be altered to make it work.
Please advise. Thank you.
The code could go anywhere you like and it should just work, by passing it a product object. Please just keep in mind that we wrote it in 2016, therefore we recommend to test it thoroughly.
If you need assistance implementing your customisation, you can contact us and we can prepare an estimate for it, after reviewing your specifications.
Thanks for your code.
Now, how to get objects (all of products) from spesific category?
This article doesn’t explain how to get the products from a specific category, as that’s outside the scope for which it was written. You can fetch products from a specific category by using the core function
wc_get_products()
. You can find more details here: https://github.com/woocommerce/woocommerce/wiki/wc_get_products-and-WC_Product_QueryWhy couldn’t you just use something like:
$terms = wp_get_post_terms( $product->id, ‘product_cat’ );
$categories[] = wp_list_pluck( $terms, ‘name’, ‘slug’ );
This would give all categories (including parent categories) in one go, maybe?
Thanks for your suggestion. We wrote the code quite a while ago, and I don’t remember why we didn’t use function `wp_get_post_terms()`. If that returns all categories, including parent ones, then it could indeed make sense to use it. It would make the code simpler, too.