Here is an alternative solution. The following function takes an array of arguments, with two possible keys:
taxonomy
: A string. The name of the Taxonomy.
level
: An int. Use 0 for the root elements, 1 for the children of the root elements, and so on.
It returns an array of WP_Term
objects.
function wpse_259499_get_subterms( $args = array() ) {
$args = wp_parse_args( $args, array( 'taxonomy' => 'category', 'level' => 0 ) );
$subterms = get_transient( 'taxonomy-subterms-' . $args['taxonomy'] . '-' . $args['level'] );
$terms_ids = array();
if ( is_array( $subterms ) ) {
return $subterms;
}
if ( 0 == $args['level'] ) {
$terms = get_terms( array(
'taxonomy' => $args['taxonomy'],
'get' => 'all',
'orderby' => 'id',
'fields' => 'id=>parent',
) );
foreach ( $terms as $term_id => $parent ) {
if ( ! $parent ) {
$terms_ids[] = $term_id;
}
}
} else if ( $hierarchy = _get_term_hierarchy( $args['taxonomy'] ) ) {
$subterms_args = array( 'taxonomy' => $args['taxonomy'], 'level' => $args['level'] - 1 );
foreach ( wpse_259499_get_subterms( $subterms_args ) as $term ) {
if ( isset( $hierarchy[ $term->term_id ] ) ) {
$terms_ids = array_merge( $terms_ids, $hierarchy[ $term->term_id ] );
}
}
}
if ( $terms_ids ) {
$subterms = get_terms( array(
'taxonomy' => $args['taxonomy'],
'get' => 'all',
'include' => $terms_ids,
) );
} else {
$subterms = array();
}
set_transient( 'taxonomy-subterms-' . $args['taxonomy'] . '-' . $args['level'], $subterms, HOUR_IN_SECONDS );
return $subterms;
}
Note 1: If you decide to rename the function, please note that the function is calling itself, so you need to change the name in the recursive call as well.
Note 2: The results are being stored in a transient for an hour. In order to get fresh results during development, you can add the following line at the beginning of the function:
delete_transient( 'taxonomy-subterms-' . $args['taxonomy'] . '-' . $args['level'] );
You may also need to delete those transients every time a category in the taxonomy of interest is added, deleted or modified, if you want to have accurate results all the time.
Example
The following code can be used in a template, to generate an unordered list of links to all terms in the selected level:
<ul>
<?php foreach ( wpse_259499_get_subterms( array( 'taxonomy' => 'category', 'level' => 0 ) ) as $term ): ?>
<li><a href="<?php echo esc_attr( get_term_link( $term ) ); ?>"><?php echo esc_html( $term->name ); ?></a></li>
<?php endforeach; ?>
</ul>