How to sort list of custom posts to get view like a tree of posts under categories and their children’s categories?

I’m new here and my english isn’t perfect so I’m sorry for this 🙂 I’m here because I’m workin on site with post list sorted by category and I have problem with sort out my posts in categories and children categories under them. Now everything is messed up. I would like to sort my custom posts like that:

CATEGORY 1

Read More
  • CHILD CATEGORY 1

    • Post
    • Post
    • Post
  • CHILD CATEGORY2

    • Post
    • Post
    • Post

CATEGORY 2

  • CHILD CATEGORY3
    • Post
    • Post
    • Post

CATEGORY 3

  • Post
  • Post

  • CHILD CATEGORY4

    • Post
    • Post
    • Post

Is it possible with this code:

<?php
$querystr = "SELECT terms.* FROM $wpdb->term_taxonomy tax LEFT JOIN $wpdb->terms terms ON       tax.term_id = terms.term_id WHERE tax.taxonomy = 'MY_CUSTOM_TAXONOMY'";

$categories = $wpdb->get_results($querystr, OBJECT);

foreach( $categories as $category ): 
echo '<div class="category-header"><h3>'.$category->name.'</h3>';  
echo '<p class="category-description">'.strip_tags(term_description($category->term_id,'MY_CUSTOM_TAXONOMY')).'</p></div>';  

$posts = get_posts( array( 'MY_CUSTOM_TAXONOMY' => $category->name, 'post_type' => 'MY_CUSTOM_POST' ) );  
foreach($posts as $post) :  
setup_postdata($post);  

 the_title();   

endforeach;

endforeach;
?>

I will be grateful for all help, thank You!!

Related posts

Leave a Reply

4 comments

  1. ok, this is my working solution:

    <?php
    
    $args=array(
    'post_type'                => 'biblioteka',
    'child_of'                 => 0,
    'parent'                   => '',
    'orderby'                  => 'name',
    'order'                    => 'ASC',
    'hide_empty'               => 1,
    'hierarchical'             => 1,
    'exclude'                  => '',
    'include'                  => '',
    'number'                   => '',
    'taxonomy'                 => 'kategoria-pozycji',
    'pad_counts'               => false
    );
    
    $categories=get_categories($args);
    
    foreach ( $categories as $category ) {
    
    if ( $category->parent > 0 ) {
    continue;   
    }
    
    echo '<h1 style="font-weight:bold">' . $category->name . '</h1>';
    
    $querystr = "SELECT $wpdb->posts.*
              FROM $wpdb->posts, $wpdb->term_relationships, $wpdb->terms
              WHERE term_id = (" . $category->cat_ID . ")
              AND term_taxonomy_id = (" . $category->term_taxonomy_id . ")
              AND ID = object_id
              AND post_type = 'biblioteka'
              AND post_status = 'publish'
              ORDER BY post_date DESC";
    $posts = $wpdb->get_results($querystr, OBJECT);
    
    echo '<ul>';
    foreach ( $posts as $post ) {
        setup_postdata($post);  
    
            echo '<li>'; the_title();   echo '</li>';
    
            }
    echo '</ul>';
    
    $categories2 = get_terms('kategoria-pozycji',array('parent' => $category->term_id , 'hide_empty'=> '0' ));
    
    foreach ( $categories2 as $category ) {
    
    echo '<h2>' . $category->name . '</h2>';
    
    $posts = get_posts( array( 'kategoria-pozycji' => $category->name, 'post_type' => 'biblioteka' ) );  
    
    echo '<ul>';
    foreach($posts as $post) { 
        setup_postdata($post);  
    
            echo '<li>'; the_title();   echo '</li>';
    
            }
    echo '</ul>';
    
    }
    }
    
    ?>
    
  2. My best solution! (works for any taxonomies,including “category”)

    $your_taxonomy='category';
    
    function my_Categ_tree($TermName='', $termID, $separator='', $parent_shown=true ){
        $args = 'hierarchical=1&taxonomy='.$TermName.'&hide_empty=0&orderby=id&parent=';
                if ($parent_shown) {$term=get_term($termID , $TermName); $output=$separator.$term->name.'('.$term->term_id.')<br/>'; $parent_shown=false;}
        $separator .= '-';  
        $terms = get_terms($TermName, $args . $termID);
        if(count($terms)>0){
            foreach ($terms as $term) {
                //$selected = ($cat->term_id=="22") ? " selected": "";
                //$output .=  '<option value="'.$category->term_id.'" '.$selected .'>'.$separator.$category->cat_name.'</option>';
                $output .=  $separator.$term->name.'('.$term->term_id.')<br/>';
                $output .=  my_Categ_tree($TermName, $term->term_id, $separator, $parent_shown);
            }
        }
        return $output;
    }
    

    Then you can output:

    1) target category(taxonomy) tree, using specific ID

    echo my_Categ_tree($your_taxonomy, 0 );
    

    2) All categories/taxonomies

    foreach (get_terms($your_taxonomy, array('hide_empty'=>0, 'parent'=>0)) as $each) {
        echo my_Categ_tree($each->taxonomy,$each->term_id);
    }
    
  3. I played a little and this is what I came up with, I tested and it works just like your given example:

    <ul>
    <?php
    
    // get initial categories
    $categories = get_categories();
    
    foreach ( $categories as $category ) {
    
    // we don't want child categories now, and since get_categories does not support 'depth' parameter, we use ->parent check
    if ( $category->parent > 0 ) {
        continue;   
    }
    
    $i = 0;
    echo '<li>' . $category->cat_name . '</li>';
    
    $posts = get_posts(
        array(
            'category' => $category->term_id
        )
    );
    
    foreach ( $posts as $post ) {
    
        // let's make sure that the post is not also in any of child categories, if it is, skip it ( we don't want to display it twice )
        $child_categories = get_term_children( $category->term_id, 'category' );
    
        if ( $child_categories && in_category( $child_categories, $post->ID ) ) {
            continue;
        }
    
        echo 0 === $i ? '<ul>' : '';
        echo '<li>' . $post->post_title . '</li>';
        $i++;
    
    }
    
    // now, after we listed all the posts, we query for child categories
    $categories2 = get_categories(
        array(
            'parent' => $category->term_id
        )
    );
    
    foreach ( $categories2 as $category ) {
    
        $j = 0;
        echo '<li>' . $category->cat_name . '</li>';
        $posts2 = get_posts(
            array(
                'category' => $category->term_id
            )
        );
    
        foreach ( $posts2 as $post ) {
    
            echo 0 === $j ? '<ul>' : '';
            echo '<li>' . $post->post_title . '</li>';
            $j++;
        }
    
        echo null === $posts2 ? '' : '</ul>';
    
    }
    
    echo null === $posts ? '' : '</ul>';
    
    }
    
    ?>
    </ul>
    
  4. Here is the solution that I solved the problems as you experience

                //Define Some require
                define(TAX_TYPE, 'category'); //you can also replace your custom taxonomy in category
                $terms = get_terms(TAX_TYPE); 
                define(WP_HOME, 'http://yourdomain.com');
    
    
            ?>
            <div class="menu-tours-container">
                <ul id="menu-tours" class="menu">
                    <?php 
                        foreach( $terms as $tax_term ) : 
    
                        $permalink = WP_HOME . '/' . TAX_TYPE . '/' . $tax_term->slug;
    
                        // getting posts from each tour type
                        $args=array(
                            'post_type'     => 'tour',
                            'post_status'   => 'publish',
                            'order_by'      => 'post_title',
                            'order'         => 'ASC',
                            'tour-type'    => $tax_term->slug
                        );
                        $posts = get_posts($args);
    
                    ?>                        
                        <li>
                            <div class="block-title">
                                <h4><?php echo $tax_term->name; ?></h4>
                            </div>
                            <ul class="check">
                                <?php foreach ($posts as $post) : ?>
                                <li><a href="<?php echo get_permalink($post->ID); ?>"><?php echo $post->post_title; ?></a></li>
                                <?php endforeach; ?>
                            </ul>
                        </li>                 
                    <?php endforeach; ?>
                </ul> <!--#menu-tours-->
    
            </div>