How to group by taxonomy on Custom Post Type archive

The question:

I have been struggling with an archive template for a custom post type. I want to display the posts grouped alphabetically by a custom taxonomy called countryname. I tried more than half a dozen examples and finally found one that almost works.

Here is my code so far. When I get this working I will pull in the postmeta, but for now I’d be happy just getting the titles under the correct country.

What I want will look something like this

Canada
 - a post 
 - another post
England 
 - this post 
United States
 - short post
 - some post 
 - that post

But right now it looks like this:

Canada
 - a post 
 - a post
England 
 - a post 
United States
 - a post
 - a post 
 - a post

I added wp_reset_postdata() But that didn’t work either. Can someone help me troubleshoot this? It seems that the problem must be in the query to return each custom post within this taxonomy category.

Thank you!

$taxonomy = array( "name" => 'countryname' , "slug" => 'countryname');
$custom_post_type = "tours";

if ( have_posts() )
the_post();
?>

<?php
// Query your specified taxonomy to get, in order, each category
$categories = get_terms($taxonomy['name'], 'orderby=title');
foreach( $categories as $category ) {
?>

<div id="content">    
<h2 class="page-title">
<?php echo $category->name; ?>
</h2>

<?php
// Setup query to return each custom post within this taxonomy category
$o_queried_posts = get_posts(array(
'nopaging' => true,
'post_type' => $custom_post_type,
'taxonomy' => $category->taxonomy,
'term' => $category->slug,
));
?>

<div id='archive-content'>

<?php
// Loop through each custom post type
foreach($o_queried_posts as $o_post) {
?>

<div id="post-<?php the_ID(); ?>">

<h2 class="entry-title"><?php the_title(); ?></h2>


</div><!-- #post -->
<?php wp_reset_postdata();
} // foreach($o_queried_posts as $o_post)  

?>
</div> <!-- archive-content -->
</div> <!-- #content -->
<?php } // foreach( $categories as $category ) 

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

You’re almost there. Since the_title inside your custom loop is one of the Post template tags you need to assign the global $post to use the new data from the custom query.

<?php
    global $post; // Access the global $post object.

    // Setup query to return each custom post within this taxonomy category
    $o_queried_posts = get_posts(array(
        'nopaging' => true,
        'post_type' => $custom_post_type,
        'taxonomy' => $category->taxonomy,
        'term' => $category->slug,
    ));
?>

<div id='archive-content'>

<?php
// Loop through each custom post type
foreach($o_queried_posts as $post) : 
    setup_postdata($post); // setup post data to use the Post template tags. ?>

    <div id="post-<?php the_ID(); ?>">

       <h2 class="entry-title"><?php the_title(); ?></h2>


    </div><!-- #post -->
<?php endforeach; wp_reset_postdata(); ?>

</div> <!-- archive-content -->

Method 2

Try this:

<?php 
    $taxonomy = array( "name" => 'countryname' , "slug" => 'countryname');
    $custom_post_type = "tours";

    if ( have_posts() ):

        // Query your specified taxonomy to get, in order, each category
        $categories = get_terms($taxonomy['name'], 'orderby=title');
        foreach( $categories as $category ):
        ?>

        <div id="content">    
            <h2 class="page-title">
            <?php echo $category->name; ?>
            </h2>

            <?php
            // Setup query to return each custom post within this taxonomy category
            $args = array(
                 'post_type' = $custom_post_type,
                 'tax_query' => array(
                        array(
                            'taxonomy' => $taxonomy["name"],
                            'terms' => $category->slug;
                        )
                    )  
                );

            $query = new WP_Query( $args );
            ?>

            <div id='archive-content'>

                <?php
                while( $query->have_posts() ): $query->the_post();
                ?>

                <div id="post-<?php the_ID(); ?>">

                <h2 class="entry-title"><?php the_title(); ?></h2>


                </div><!-- #post -->
                <?php
                endwhile(); 
                wp_reset_postdata();
                ?>
            </div> <!-- archive-content -->
        </div> <!-- #content -->
        <?php endforeach; // foreach( $categories as $category )
    endif;?> 


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment