Here’s how you get all top-level categories and loop them to create a list of links,
$parent_categories = get_categories( array(
'fields' => 'id=>name', // other term data no needed here
'parent' => 0,
));
$parent_category_links = array();
foreach ($parent_categories as $parent_category_id => $parent_category_name) {
$parent_category_links[] = sprintf(
'<li><a href="%s">%s</a></li>',
esc_url( get_term_link( $parent_category_id, 'category' )),
esc_html( $parent_category_name )
);
}
echo '<ul>' . implode('', $parent_category_links) . '</ul>';
Clicking on a category link created by the above loop will take the user to the category’s archive view (category.php / archive.php / index.php), where you can show a list of sub-categories. Like so,
$child_categories = get_categories( array(
'fields' => 'id=>name', // other term data no needed here
'parent' => get_queried_object_id(), // you should check that current object is a WP_Term, if you're using generic archive or index template
));
if ( $child_categories ) {
$child_category_links = array();
foreach ($child_categories as $child_category_id => $child_category_name) {
$child_category_links[] = sprintf(
'<li><a href="%s">%s</a></li>',
esc_url( get_term_link( $child_category_id, 'category' )),
esc_html( $child_category_name )
);
}
echo '<ul>' . implode('', $child_category_links) . '</ul>';
} else {
// The Loop to display posts
}
The above code is a simplified example and you should modify it to match your exact needs and setup.
P.s. get_categories()
returns array of WP_Terms by default. To access the term id, you should use $term->term_id
.