Display the deepest child category from Category X (in loop)

The code you referenced in your question is flawed. In most cases it will work but it relies on an assumption that newer child terms are created after their parents, and as a result, have higher IDs.

To fool the code you posted, do this:

  • Create a new category
  • Edit an older child term
  • Change its parent to the new category
  • Make sure it has a different depth

You also have the other problem of specificity. In your example, you specify that it should look inside sport, not all, but how would the code know to look specifically in sport? This sounds like you plan to hardcode the Sport category name or ID into your code, which I STRONGLY advise against. Instead a post meta value or metabox UI would be better but not ideal.

Your question can be distilled to this:

Given a post A, and a term B, what is the deepest child term of B on post A? Where B is of taxonomy ‘category’.

This gives us 2 new questions:

  1. How do you determine if term A contains term B?
  2. How do you find out how many ancestors/parents a term has?

The answers to those questions would implement these 2 functions:

  • get_term_depth( $term ) – returns the depth or number of parents a term has
  • is_term_ancestor( $term, $ancestor ) – is this term an ancestor of another term? Returns true or false

These functions are not a part of WordPress core, and will need to be written.

But if using these 2 functions we could then do this:

function get_deepest_child_term( $terms, $specific_term ) {
    $deepest_term = $specific_term;
    $deepest_depth = get_term_depth( $specific_term );
    foreach ( $terms as $term ) {
        if ( is_term_ancestor( $term, $specific_term ) ) {
            $depth = get_term_depth( $term );
            if ( $depth > $deepest_depth ) {
                $deepest_term = $term;
                $deepest_depth = $depth;
            }
        }
    }
    return $deepest_depth;
}

Which you could then use like this:

$terms = wp_get_object_terms( $post_id, 'category' );
$sport_term = get_term_by( 'slug', 'sport', 'category' );
$deepest_term = get_deepest_child_term( $terms, $sport_term );
echo $deepest_term->name;

You’ll note I went directly to the taxonomy term API rather than using the higher level middle men such as get_the_category. This way the code is just as valid for custom taxonomies. E.g. a product category.

The implementation of get_term_depth and the implementation of is_term_ancestor I leave as a task to the reader, and encourage 2 new questions be asked, as they are each useful and interesting questions in their own right. It’s important to break down a task into smaller parts, repeating the process until each part is solvable or bite sized. Both functions would require an understanding of recursion to implement.

Leave a Comment