| Posted under Development

WordPress wp-query: Order posts by taxonomy

A few days ago as i was working on a project, i needed to query some custom post types and order them by a custom taxonomy.

More specifically, i had a list of taxonomies (in my case a Timeline Group that categorizes the posts) and a list of posts assigned to each taxonomy (in my case a list of Timeline entries).

The first solution was to query for all taxonomies and then inside a loop, query all posts assigned to each taxonomy.

However, i did not want to make 6 queries (as many as my taxonomies) in the database.

I am using the “Post Types Order” plugin that i find very useful, as my client can easily drag & drop the posts in the order that he likes.
However, in the settings i have disabled the “Auto-sort” option as i prefer to make my own queries.

Normally, to get a list of all of my posts (custom post type named “timeline”) i would type:

$timeline = new WP_Query(array(
    'post_type' => 'timeline',
    'post_status' => 'publish',
    'orderby' => array('menu_order' => 'ASC', 'date' => 'DESC'),   //keeps the order from the drag & drop and also orders by the newest first
    'update_post_meta_cache' => false,
    'update_post_term_cache' => false,
    'ignore_sticky_posts' => true,
    'posts_per_page' => -1,  //get all posts matching the above criteria
    'no_found_rows' => true,
));

Now, i want to force WP_QUERY to use the taxonomy table and change the orderby.

So first i am going to query all taxonomies and get their IDs and then i will call my own filters to change the order by of the query.

$timeline_taxonomies = get_terms(array(
    'fields' => 'ids',   //get the IDs
    'taxonomy'     => 'taxonomy_name',
    'orderby'      => 'term_order',
    'hide_empty'   => true,
));

//add my filter to change the order by of the query done by WP_QUERY:
add_filter('posts_orderby', 'my_timeline_orderby');

function my_timeline_orderby($orderby_statement) {
    $orderby_statement = " term_order ASC, ".$orderby_statement; //keeps the current orderby, but also adds the term_order in front
    return $orderby_statement;
}

$timeline = new WP_Query(array(
    'post_type' => 'timeline',
    'post_status' => 'publish',
    'orderby' => array('menu_order' => 'ASC', 'date' => 'DESC'),
    'update_post_meta_cache' => false,
    'update_post_term_cache' => false,
    'ignore_sticky_posts' => true,
    'posts_per_page' => -1,
    'no_found_rows' => true,
    //same as the initial query, only now i am adding 'tax_query' just to force an inner join to the taxonomies table
    'tax_query' => array(
        array(
            'taxonomy'  => 'taxonomy_name',
            'field'     => 'term_id',
            'terms'     => $timeline_taxonomies
        )
    ),
));

//after i am done, i remove the filter:
remove_filter('posts_orderby', 'my_timeline_orderby');

//now i can loop though the results as i would normally do:

foreach ($timeline->posts as $post){
   //code here
}

Hope this helps!

Thanks for your likes, this will motivate me to write posts more often!