I want to get a list of products of a given category from WP_query, but it won't work like it should.

I've done this :

$args = array( 
    'post_type' => 'product',
    'product_cat' => 17,
$products = new WP_Query($args);

But this returns every product from my shop ... I have also tried with 'cat', 'category' and 'category_name' attr with same result.

I've tried using tax_query :

$args = array( 
    'post_type' => 'product',
    'tax_query' => array(
        'taxonomy' => 'product_cat',
        'terms'    => 17
$products = new WP_Query($args);

And this also returns every products I have also tried with 'cat', 'category' and 'category_name' with same result.

I have managed using the following code to get regular posts from a given category.

$args = array( 
    'post_type' => 'post',
    'cat'       => 22
$posts = new WP_Query($args);

A couple more things :

  • I am certain I have the right category id.
  • tax_query worked for the posts too
  • edit : tax_query returns every products, ignoring my product_cat attr

    I have been looking to do this for days and tried every possible solution of similar questions on stack and other sites without success... Why doesn't it work for products ?

EDIT : the code snipet with tax_query was wrong so I changed it.

EDIT 2 : I have tried several new Things, here is the summary :

  • disabled all custom hooks : same results
  • instantiated a WC_Product manually by the id of an actual product as an argument. It shows that its category_ids attribute is empty, even though the product does have a category on the admin panel... and the category taxonomy page shows the right stuff too.
  • when I do var_dump(get_the_terms($postID, 'category')); on a regular post it works fine

EDIT 3 : - disabled all plugins but Woocommerce with same result... - when I do var_dump(get_post_types());, the product post type does not show. And so naturally, when I do var_dump(get_object_taxonomies('product'));, it returns an empty array.

  • 'cat', 'category', 'category_name', and 'product_cat' won't work as arguments because product categories are a separate taxonomy to categories, and you need a tax_query to query custom taxonomies. There is nothing wrong with the code for the tax query I can see here. Either the ID actually is wrong, or product and product_cat aren't the right names for the post type and taxonomy. They would be if you're using WooCommerce. Are you? Mar 3, 2018 at 11:45
  • Also make sure you're not using the pre_get_posts hook anywhere in such a way that could interfere with this query. Mar 3, 2018 at 11:51
  • Did you try to add 'suppress_filters' => false ? Just an idea from the top of my head. Don't know if there any filters in place to suppress since you haven't mentioned what you use for the products.
    – Beee
    Mar 3, 2018 at 12:31
  • @JacobPeattie I do use woocommerce for this. for the category ID, I have checked the URL parameters in the admin panel when editing a category so it should be the right one. How do I find the right taxonomy for a product category then ? @Beee 'suppress_filters does not change anything
    – Maayam
    Mar 3, 2018 at 12:42
  • product_cat is correct for WooCommerce. Is this the actual code you’re using? Or an example? And issue could exist isn’t he actual code that’s not present in this example, because this code is fine. Mar 3, 2018 at 12:43

2 Answers 2


In the end my main problem turned out to be that I was executing code right into functions.php (for testing purpose). The code was executing before woocommerce was initialized and then was failing to fetch products correctly. Despite that, I couldn't get Wp_Query to return only products of one given category. It was still returning every product from my database so I found a way around it.

$category; //this is the var containing the wanted category slug
$productPosts = new WP_Query(array(
    'post_type' => 'product'

//I could have used $productPosts->have_posts() here but I decided not to use it in my particular context
foreach ($productPosts->posts as $p) {
    $currentProduct = new WC_Product_Variable($p->ID);

    //I can only access category ids with WC_Product so I'm building an array of category slugs instead
    foreach ($currentProduct->get_category_ids() as $catId) {
        if( $term = get_term_by( 'id', $catId, 'product_cat' ) ){
            array_push($categories, $term->name); //push it

    if(in_array($category, $categories)){ //if the current currentProduct has the asked category,
        //push it in $currentProduct into $products array
        array_push($products, $currentProduct);
    else{//current product doesn't have asked category
} //end foreach, we now have all products of asked category... in $products array

This works... But really, it feels wrong. I'm making several database queries for each product I want to include in my final array... Is this how woocommerce is supposed to work ? Also, I'm not sure how i'm supposed to paginate with this data but anyway it's not my concern here...

There must be a better way to do this but I couldn't find it for now...


I know, I'm too late to answer this question but it helps others.

$args = array(      
        'post_type' => 'product',
        'post_status' => 'publish',
        'tax_query' => array(
                            'taxonomy' => 'product_cat',
                            'field'    => 'term_id',
                            'terms'    => array($cat_id1,$cat_id2),

$query = new WP_Query($args);

It's tested and worked on WC 3.9.1

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.