Listing Child categories under another child category

The missing part from what you’ve written in code is the idea of putting extra foreach loops inside the foreach loop you already have to go one level deeper. Likewise recursion would have solved this, but it’s unlikely it would have been helpful once it was revealed what you were trying to build.

  • foreach child term
    • print that child term
    • fetch the grandchildren, aka the children of the child term
    • foreach grandchild term
      • print the grandchild term
      • fetch the great-grandchildren, aka the children of the grandchild term
      • foreach great-grandchild term
        • print the great-grandchild term
        • fetch the great-great-grandchildren aka the children of the great-grandchild term
        • foreach great-great-grandchild term
          • print the great-great-grandchild term
          • etc etc

Notice how each loop does the same thing but is nested one level deeper?

For example this prints out a list of child terms, with sub-lists of grandchild terms:


// ## display the child terms
$child_terms = get_terms( [
    'taxonomy' => 'products-category',
    'parent' => get_queried_object_id(),
] );
if ( ! is_wp_error( $child_terms ) ) {
    echo '<ul>';
    foreach ( $child_terms as $child_term ) {
        echo '<li>' . $child_term->name . '</li>';

        // ### display the grandchild terms
        $grandchild_terms = get_terms( [
            'taxonomy' => 'products-category',
            'parent'   => $child_term->parent,
        ] );
        if ( ! is_wp_error( $grandchild_terms ) ) {
            echo '<ul>';
            foreach ( $grandchild_terms as $grandchild_term ) {
                echo '<li>' . $grandchild_term->name . '</li>';

                // #### display the great-grandchild terms.. etc
                $greatgrandchild_terms = get_terms( [
                    'taxonomy' => 'products-category',
                    'parent' => $grandchild_term->parent,
                ] );
                if ( ! is_wp_error( $greatgrandchild_terms ) ) {
                    // etc...


            }
            echo '</ul>';
        }
        echo '</ul>';
    }
}

You could add additional loops inside the deepest foreach to grab 3, 4, or more levels deeper.

Note that earlier I mentioned recursion, this would allow you to write a single function that went infinitely deep, but this probably won’t help you since you want to display each level using different HTML in different places.

For example:

function display_product_categories_as_list( int $term_id ) : void {
    $child_terms = get_terms( [
        'taxonomy' => 'products-category',
        'parent'   => $term->term_id,
    ] );
    if ( ! is_wp_error( $child_terms ) ) {
        echo '<ul>';
        foreach ( $child_terms as $child_term ) {
            echo '<li>' . $child_term->name . '</li>';
            display_product_categories_as_list( $child_term );
        }
    }
}

display_product_categories_as_list( get_queried_object_id() );

That would display the entire tree of terms as a list with child terms indented, but they would all be displayed the same, and it would go past 3 levels. Notice the function calls itself inside the loop, this is a basic form of recursion. Instead manual nested loops would work better for your use case.

tech