When working with categories in WordPress, you may at times need to get categories that are at a certain level. For example, let’s say that you are dealing with locations and you have categories listed in this format: Country (level I) -> State (level II) -> City (level III). If you want to get only Cities which is at level 3, then stick around and I’ll show you how.

WordPress does not have a specific hook/function to deal with this scenarios but it does provide functions that will help you filter this information, based on the level that you want to get. So, let’s start with a block of code that returns all categories:

 


$defaults = array(
'taxonomy' => $taxonomy,
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => 0,
'exclude' => array(),
'exclude_tree' => array(),
'number' => '',
'offset' => '',
'fields' => 'all',
'name' => '',
'slug' => '',
'hierarchical' => true,
'search' => '',
'name__like' => '',
'description__like' => '',
'pad_counts' => false,
'get' => '',
'childless' => false,
'cache_domain' => 'core',
'update_term_meta_cache' => true,
'meta_query' => ''
);

$locations = get_terms( $defaults );

So far the above code will return a list of location terms defined by the $taxonomy variable, which you need to change to your specific taxonomy. Now that we have a list of location categories (or whatever your category is), we need to filter only level 3. The way we do that is by introducing get_ancestors() function which would fetch us the ancestors for each term. Just like with humans who can have parents, grandparents and great grandparents, this function will tell us how many ancestors each term has. So level 2 categories have 1 ancestor, level 3 categories have 2 ancestors etc.

Now, let’s filter our locations list of categories to include only cities.

 

foreach($locations as $loc) {
$ancestors = get_ancestors($loc->term_id, 'ad_country');
if( count($ancestors) == 2) {
$cities[] = $loc;
}
}

In the code above, we use the get_ancestors() function, pass in the term id and the name of taxonomy, and get back an array of ancestors. Using the count() function we can get the number of ancestors and check against the level that we want.

In summary, here’s the full code encased in a function that you can just copy and paste:

 

function f2b_get_cities() {
$cities = array();
$taxonomy = "location_tax";
$defaults = array(
'taxonomy' => $taxonomy,
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => 0,
'exclude' => array(),
'exclude_tree' => array(),
'number' => '',
'offset' => '',
'fields' => 'all',
'name' => '',
'slug' => '',
'hierarchical' => true,
'search' => '',
'name__like' => '',
'description__like' => '',
'pad_counts' => false,
'get' => '',
'childless' => false
);

$locations = get_terms( $defaults );
foreach($locations as $loc) {
$ancestors = get_ancestors($loc->term_id, $taxonomy);
if( count($ancestors) > 1) {
$cities[] = $loc;
}
}
return $cities;
}