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.