In resetting the main query for category pages for a custom post type, I would like to write one test for a parent category and have it test positive for all child categories, recursively.

For example, if the category is Lumber, I am resetting the main query to pick up data in a Custom Post type for lumber.

Currently, the code looks like this:

    if (!is_admin() && $query->is_main_query() && (is_category('Lumber') || is_category('Domestic Hardwoods')) )

While I can add all the subcategories manually, it would mean inconvenience for my client if they wish to add a new subcategory. Recursion should fix that UX problem.

1 Answer 1


Note that is_category() accepts a category ID, name, slug, or array of such, so you could actually simply use is_category( array( 'Lumber', 'Domestic Hardwoods' ) ) instead of having to call is_category() twice.

But as for what you asked, is_category() does not support that, however, what you are trying to do can be achieved like so, which uses get_term_children():

if ( ! is_admin() && $query->is_main_query() && $query->is_category() ) {
    $current_cat = get_queried_object();
    // replace 'parent' with the correct category slug
    $parent_cat  = get_term_by( 'slug', 'parent', 'category' );
//  $parent_cat  = get_term_by( 'name', 'Parent', 'category' );
//  $parent_cat  = get_term( 123 );

    // Get the child categories/IDs.
    $children = get_term_children( $parent_cat->term_id, 'category' );

    $cat_ids = array_merge( array( $parent_cat->term_id ), $children );

    // Check whether it's the parent category's archive or its children's.
    if ( in_array( $current_cat->term_id, $cat_ids ) ) {
        // put your awesome code here...

So the only hard-coded database value is the parent category's slug, but you can also use its name or ID, if you want to.

  • So basically, your answer uses 2 tests (if): 1) the original test returns positive for categories generally, 2) the second test checks categories against a list of the parent its child categories. The code in the middle builds the list (array). Aug 18, 2022 at 16:08
  • 1
    Yes, that's correct, and you could also replace the $cat_ids and the if that follows, with if ( $current_cat->term_id === $parent_cat->term_id || in_array( $current_cat->term_id, $children ) )
    – Sally CJ
    Aug 18, 2022 at 16:19
  • 1
    Bingo! Better UX for my client is now in place. Aug 18, 2022 at 16:28

Your Answer

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

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