WordPress post counts by year and category

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.

Leave a Reply