I’m sure there are many ways to do this but it was a pretty specific request. They wanted a by year count of posts in all the categories. After a bit of looking around I just wrote a plugin. Most of the explanation is in the code comments.
Get the first year where we have posts
//get the first year you have for posts function dlinq_get_first_post_year(){ $post = get_posts(array( 'post_type' => 'post', 'order_by' => 'publish_date', 'order' => 'ASC',//start with the oldest 'posts_per_page' => 1,//we only need one )); return $first_year = substr($post[0]->post_date, 0, 4);//chop out everything but the year }
The range of years
Now that we have the oldest year and we can get the current year . . . I don’t want to hand fill in the years in between. That’s where PHP’s range function comes in.
function dlinq_cat_counter(){ if(current_user_can('administrator')){//only for us admins $this_year = date("Y"); //get current year $years = range($this_year, dlinq_get_first_post_year());//create array of years from earliest post year to now $content = ''; foreach ($years as $key => $year) { // code... $content .= dlinq_by_year($year); } return $content; } else { return "<p>Please login to access this information.</p>"; } }
Category Query Loop
Nothing fancy, just looping through with the year variable in combination with the category id for the query. I do like using the PHP/HTML content with the curly braces. It feels sensible to me and easy to manage. I’m sure others disagree.1
function dlinq_by_year($year){ $html = ''; $cat_args = array( 'taxonomy' => 'category', 'orderby' => 'name', 'order' => 'ASC', ); $cat_ids = get_terms($cat_args); //get all the categories $html = "<h2>{$year}</h2>"; $html .= "<ul>"; foreach ($cat_ids as $key => $cat_id) { // code... $args = array( 'post_type' => 'post', 'cat' => $cat_id->term_id, 'date_query' => array( array( 'year' => $year, //just the year in question ), ) ); $year_query = new WP_Query($args); $cat_name = $cat_id->name; $cat_slug = $cat_id->slug; $count = $year_query->found_posts; $html .= "<li data-count='{$count}' data-name='{$cat_slug}'>{$cat_name} - {$count}</li>"; } $html .= "</ul>"; return $html; }
1 The only things I am sure of is that people will disagree with any opinion and that there are lots of different ways to do things.