Sort posts by custom taxonomy name

Is it possible to sort posts (custom post type) by category / taxonomy (name, desc)?

For example my categories would be

  • Season 2012
    • some post
    • some post
    • some post
  • Season 2011
    • some post
    • some post
    • some post
  • Season 2010
  • etc..

Related posts

Leave a Reply

3 comments

  1. One solution would be-

    $terms = get_terms('taxonomy-name');
    foreach($terms as $term) {
        $posts = get_posts(array(
                'post_type' => 'custom_post_type_name',
                'tax_query' => array(
                    array(
                        'taxonomy' => 'taxonomy-name',
                        'field' => 'slug',
                        'terms' => $term->slug
                    )
                ),
                'numberposts' => -1
            ));
        foreach($posts as $post) {
            // do what you want to do with the posts here
        }
    }
    
  2. I know this is an old question that’s already got a great answer, but I struggled with something very similar for hours today and came up with an alternate loop.

    You can also customize Mridul’s (excellent) solution a bit if you want to make this work on the archive page for a taxonomy. In other words, you can sort a custom taxonomy archive by another taxonomy using this solution.

    I’m sharing this because I spent four hours struggling with this problem today, and if anybody else is trying to create custom taxonomy archives sorted by a different taxonomy, this is how you do it. (Also, this is my first answer on StackExchange รขย€ย” please be nice! ๐Ÿ™‚ )

    This begins exactly like Mridul’s solution. Query the taxonomy you want to sort your posts by.

    $terms = get_terms( array(
        'taxonomy' => 'custom_taxonomy_one',
        'parent' => 0, // This helped me eliminate repetitive taxonomies; you may want to skip this
    ) );
    
    foreach($terms as $term) {
        echo '<h2>' . $term->name . '</h2>'; // Echo the name of the term
    

    This is where it gets a bit different from Mridul’s answer. You want to query two taxonomies, and make sure that the relationship between them is set to be “AND”, which means that the listed posts meet the criteria of being in both taxonomies.

    In this case, the posts in “custom_post_type” must match the first term’s slug and another’s name. Hopefully the code makes sense to everybody!

        $posts = get_posts(array(
                'post_type' => 'custom_post_type', // Get posts from custom post type
                'tax_query' => array(
                    'relation' => 'AND', // posts must match both taxonomies
                    array(
                        'taxonomy' => 'custom_taxonomy_one',
                        'field' => 'slug',
                        'terms' => $term->slug // match the slug for the term in the previous array
                    ),
                    array(
                        'taxonomy' => 'custom_taxonomy_two',
                        'field' => 'slug',
                        'terms' => 'custom_taxonomy_two_term_name'
                    )
                ),
                'numberposts' => -1
            ));
        foreach($posts as $post) {
           // Do Yo Thang
        }
    }
    
  3. Alternative loop, where tax = category and custom post type = "results"

    $args = array( 'taxonomy' => 'category' );
    $terms = get_terms( 'category', $args);
    
    //START FOR EACH LOOP
    foreach ($terms as $term) {
    
                $post_type = 'results';
                $tax = 'category';
                $tax_terms = get_terms( $tax );
                if ($tax_terms) {
                    foreach ($tax_terms  as $tax_term) {
                    $args = array(
                        'post_type' => $post_type,
                        "$tax" => $tax_term->slug,
                        'post_status' => 'publish',
                        'posts_per_page' => -1,
                        'caller_get_posts'=> 1
                    );
    
    
    
                    $my_query = null;
                    $my_query = new WP_Query($args);
    
                    if( $my_query->have_posts() ) : ?>
    
                            // WHILE
                            <?php while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
    
                            // Do stuff
    
                            <?php endwhile; ?>
                            // END WHILE
    
    
                    <?php else : ?>
        <?php endif; wp_reset_query(); ?>
    
    }
    // END FOR EACH LOOP