List taxonomy terms plus their latest post ordered by post date

Right now you are performing the query by term, and displaying results instantly. What you need is to gather the results of each query, sort them and then display separately.

Make sure to read code comments.


/* $custom_terms = get_terms('columna'); - this approach is depreciated */
$custom_terms = get_terms( array( 
    'taxonomy' => 'columna' 
) );


// store each posts in this array along with the term information
$sorted_posts = array();

foreach ( $custom_terms as $custom_term ) {
    $args = array(
        'post_type' => 'post',
        'posts_per_page' => 1,
        'orderby' => 'date',
        'order' => 'DESC',
        'suppress_filters' => true,
        'tax_query' => array(
            array(
                'taxonomy' => 'columna',
                'field' => 'slug',
                'orderby' => 'date',
                'order' => 'DESC',
                'terms' => $custom_term->slug
            )
        )
     );

     $posts = get_posts( $args );

     if ( ! empty( $posts ) ) {
        foreach ( $posts as $post ) {
            // storing term, post & data as an array item
            $sorted_posts[] = array(
                'term' => $custom_term,
                'post' => $post,
                'date' => $post->post_date
            );
        }
    }
}

/* 
 * now we will sort $sorted_posts to be displayed by date descending. 
 * note: it's compltely fine if you query more than one post from each term.
 */
uasort( $sorted_posts, function( $a, $b ){
    if ( $a['date'] == $b['date'] ) {
        return 0;
    }
    return ( $a['date'] > $b['date'] ) ? -1 : 1;
});


/*
 * $sorted_posts contains all of our posts in order. 
 * now we will group posts by same term
*/

$terms_posts = array();
foreach ( $sorted_posts as $sorted_post ) {
    if ( ! isset( $terms_posts[ $sorted_post['term']->term_id ] ) ) {
        $terms_posts[ $sorted_post['term']->term_id ] = array(
            'term' => $sorted_post['term'],
            'posts' => array()
        );
    }

    $terms_posts[ $sorted_post['term']->term_id ]['posts'][] = $sorted_post['post'];
}

// just clearing array keys to be incremental. not needed, just to be organized.
$terms_posts = array_values( $terms_posts );


// make the $post variable global so that we can use setup_postdata function.
global $post;

foreach ( $terms_posts as $term_posts ) {
    echo '<h4>'. $term_posts['term']->name.'</h4>';
    foreach ( $term_posts['posts'] as $post ) {

        // following function has made our post object global. it makes sure get_permalink, get_title etc function refers to the current post in loop.
        setup_postdata( $post );

        echo '<a href="'. get_permalink() .'">'. get_the_title() .'</a><br>'. get_the_date() .'<br>';
    }
}

// as we had modified the global post object, we have to restore it.
wp_reset_postdata();

Leave a Comment