Check if a post is in any child category of a parent category

In a site I'm developing, I have the following category structure:

* movies (parent)
    * thriller (child)
    * comedy (child)
    * drama (child)

The current post is in the comedy category. The has_term function with the following parameters returns true:

has_term( 'comedy', 'category' )

But, the same function with the following parameters returns false:

has_term( 'movies', 'category' )

My question is, is there a core function to check if the current post is in any child category of a specific parent category? If not, how can I check this?

Thanks in advance

Topic children terms taxonomy categories Wordpress

Category Web


If you want any nesting depth, use get_posts.

/**
 * Checks if the post is in one of the categories or any child category. 
 * 
 * @param  int|string|array $category_ids (Single category id) or (comma separated string or array of category ids).
 * @param  int              $post_id      Post ID to check. Default to `get_the_ID()`.
 * @return bool true, iff post is in any category or child category.
 */
function is_post_in_category( $category_ids, $post_id = null ) {
    $args = array(
        'include'  => $post_id ?? get_the_ID(),
        'category' => $category_ids,
        'fields'   => 'ids',
    );
    return 0 < count( get_posts( $args ) );
}

You can expand on this function in many ways. Maybe pass an array of post ids and filter out some or allow the query to be refined.


Add the following to your theme's functions.php:

/**
 * Tests if any of a post's assigned categories are descendants of target categories
 *
 * @param int|array $cats The target categories. Integer ID or array of integer IDs
 * @param int|object $_post The post. Omit to test the current post in the Loop or main query
 * @return bool True if at least 1 of the post's categories is a descendant of any of the target categories
 * @see get_term_by() You can get a category by name or slug, then pass ID to this function
 * @uses get_term_children() Passes $cats
 * @uses in_category() Passes $_post (can be empty)
 * @version 2.7
 * @link http://codex.wordpress.org/Function_Reference/in_category#Testing_if_a_post_is_in_a_descendant_category
 */
if ( ! function_exists( 'post_is_in_descendant_category' ) ) {
    function post_is_in_descendant_category( $cats, $_post = null ) {
        foreach ( (array) $cats as $cat ) {
            // get_term_children() accepts integer ID only
            $descendants = get_term_children( (int) $cat, 'category' );
            if ( $descendants && in_category( $descendants, $_post ) )
                return true;
        }
        return false;
    }
}

Use the function to check the parent category ID, not name or slug. I.e. if the 'movies' category ID is 50:

if ( post_is_in_descendant_category( 50 ) ) {
    // do something
}

If you don't know the 'movies' category ID, you could retrieve the ID using get_term_by() and pass it to post_is_in_descendant_category():

$category_to_check = get_term_by( 'name', 'movies', 'category' );

if ( post_is_in_descendant_category( $category_to_check->term_id ) ) {
    // do something
}

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.