Sort by latest post for wp_list_categories

One of my developer friend asked me if we could sort by last post using wp_list_categories function for WordPress. By default, wp_list_categories accept arguments for order by ID, name, slug, count or term_group. Order by latest post is not possible by default, but with a little of tweak using filter hook, we can. 🙂

First, we’ll looking at the function wp_list_categories. This function made call to get_categories to get the list of categories, which made another call to get_terms. Categories in WordPress is basically terms with category taxonomy. Finally, looking on the get_terms function, we will find some delicious filter hook that suitable for our customization.

To be able to change the order, we will have to find a way to manipulate the SQL query and add our magic. Finally, we found the filter hook to add the magic, terms_clauses. The code to call the apply filter is as below:

$pieces = array( 'fields', 'join', 'where', 'orderby', 'order', 'limits' );
$clauses = apply_filters( 'terms_clauses', compact( $pieces ), $taxonomies, $args );

As you can see, the $pieces hold a separate pieces of the SQL query. We can add our own query to this separate pieces to form a query for our need. The code we used is as follow:

function filter_term_sort_by_latest_post_clauses( $pieces, $taxonomies, $args )
    global $wpdb;
    if ( in_array('category', $taxonomies) && $args['orderby'] == 'latest_post' )
        $pieces['fields'] .= ", MAX(p.post_date) AS last_date";
        $pieces['join'] .= " JOIN $wpdb->term_relationships AS tr JOIN $wpdb->posts AS p ON p.ID=tr.object_id AND tr.term_taxonomy_id=tt.term_taxonomy_id";
        $pieces['where'] .= " GROUP BY t.term_id";
        $pieces['orderby'] = "ORDER BY last_date";
        $pieces['order'] = "DESC"; // DESC or ASC
    return $pieces;
add_filter('terms_clauses', 'filter_term_sort_by_latest_post_clauses', 10, 3);

Add this to functions.php or on your own plugin code, or where ever you wanted, it just needed to be placed before any call of wp_list_categories. Note that we only add this filter if the taxonomy is category, and if the orderby argument is set to latest_post. So our call to wp_list_categories is now:

wp_list_categories(array('orderby' => 'latest_post'))

Now your wp_list_categories call will have option to sort by latest post. 🙂

Hope it’s useful for you. Comments is appreciated. 😀

7 comments | Leave a comment

  1. takien January 26, 2012 12:55

    thanks bro, I’ll try it.:)

  2. takien January 26, 2012 21:29

    actually $pieces[‘order’] should be stripped.

    • keaglez February 4, 2012 01:47

      Well, yeah, it could be stripped. I leave it there because I think the latest post is supposed to have descending order only. Ascending order might have unexpected result.

  3. Mark August 27, 2013 02:15

    Thanks for the code. I have made one improvement, which is to filter the posts so that only published posts will influence the sort order.

    Change line 8 in your second snippet to:
    $pieces[‘where’] .= ” AND p.post_status=’publish’ GROUP BY t.term_id”;

  4. Raquel November 13, 2014 03:33

    Thank you so much for this! It worked perfectly for my needs.

  5. Lior August 14, 2017 16:41

    Years later, does it still work? It seems too sensitive for me to add a code that relies so much on internal WordPress SQL instead of on API.

    Is there any chance to have something like add_filter( ‘widget_categories_args’, …) instead?

    • Jeffri August 24, 2017 13:18

      Hey Lior, I haven’t tested myself on the latest WordPress, but I still see the filter there, so I think it should still work. I don’t think we can have a solution that doesn’t involve editing the SQL for this specific purpose.


Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.