Output parent/child categories and posts in that parent/child hierarchy

You’re right that we need to handle parent-child relationships differently. Let me explain the approach and then show you the code changes needed.

The key is to:

  • First get only top-level categories (parent = 0)
  • For each top-level category, check for child categories
  • Display the hierarchy properly in the accordion
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> 
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<?php
echo '<div class="accordion">';

// Get only top-level categories
$args = array(
    'parent' => 0,
    'orderby' => 'name',
    'order' => 'ASC'
);
$parent_categories = get_categories($args);

foreach ($parent_categories as $parent_category) {
    // Display parent category
    echo '<h2>' . $parent_category->name . '</h2>';
    echo '<div><p>';
    
    // Get posts for parent category
    $parent_args = array(
        'post_type' => array('post','book','video'),
        'posts_per_page' => -1,
        'orderby' => 'date',
        'order' => 'DESC',
        'post_status'=> 'publish',
        'cat' => $parent_category->term_id
    );
    
    $parent_posts = new WP_Query($parent_args);
    while ($parent_posts->have_posts()) {
        $parent_posts->the_post();
        echo get_the_date();
        echo '&nbsp;';
        $post_type = get_post_type();
        echo 'Type: ';
        echo ucfirst($post_type); 
        echo '&nbsp;';
        echo '<a target="_blank" href="';
        the_permalink();
        echo '">';
        the_title();
        echo '</a>';
        echo '&nbsp;';
        echo wp_trim_words(get_the_excerpt(),20,'...');
        echo '<br />';
    }
    wp_reset_postdata();
    
    // Get child categories
    $child_args = array(
        'parent' => $parent_category->term_id,
        'orderby' => 'name',
        'order' => 'ASC'
    );
    $child_categories = get_categories($child_args);
    
    // Display child categories and their posts
    foreach ($child_categories as $child_category) {
        echo '<h3>' . $child_category->name . '</h3>';
        echo '<div><p>';
        
        $child_post_args = array(
            'post_type' => array('post','book','video'),
            'posts_per_page' => -1,
            'orderby' => 'date',
            'order' => 'DESC',
            'post_status'=> 'publish',
            'cat' => $child_category->term_id
        );
        
        $child_posts = new WP_Query($child_post_args);
        while ($child_posts->have_posts()) {
            $child_posts->the_post();
            echo get_the_date();
            echo '&nbsp;';
            $post_type = get_post_type();
            echo 'Type: ';
            echo ucfirst($post_type); 
            echo '&nbsp;';
            echo '<a target="_blank" href="';
            the_permalink();
            echo '">';
            the_title();
            echo '</a>';
            echo '&nbsp;';
            echo wp_trim_words(get_the_excerpt(),20,'...');
            echo '<br />';
        }
        wp_reset_postdata();
        echo '</p></div>';
    }
    
    echo '</p></div>';
}

echo '</div>';
?>
<script>
jQuery(document).ready(function() {
    jQuery(".accordion").accordion({
        collapsible: true,
        clearStyle: true,
        active: false,
    });
});
</script>
  • First, we get only top-level categories using get_categories() with ‘parent’ => 0
  • For each parent category, we:
    • Display the parent category name as an accordion header ()
    • Show all posts belonging to that parent category
    • Get all child categories of that parent
    • For each child category, display it as a sub-header () with its posts

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)