Wordpress - Category archive by year with permalink support /category/YYYY

What you're looking for is an endpoint. There are already several of these built in: /feed/some-feed/ for feeds or /trackback/ on posts. Those are both endpoints.

Fortunately, WordPress provides a handy function makes adding your own endpionts really easy. add_rewrite_endpoint

This is all the code you need to make your yearly category archives work:

<?php
add_action( 'init', 'wpse31422_init' );
function wpse31422_init()
{
    add_rewrite_endpoint( 'year', EP_CATEGORIES );
}

As a plugin: https://gist.github.com/1296860

It works exactly like Stephen Harris' answer, and you can reach a yearly, category archive by visiting yoursite.com/category/some-cat-slug/year/2011/.

Adding an endpoint creates a query variable with the same name as the first argument of the add_rewrite_endpoint function. In this case, year. Because this query var already exists in WP (to take care of the data-based archives), we don't really have to do anything special here.


This isn't tested, but try (after you added the code you'll need to go to settings> Permalinks and click save for it to take effect):

add_action('generate_rewrite_rules', 'my_rewrite_rules');
function my_rewrite_rules( $wp_rewrite ) {
  $new_rules = array(
     '(.+)/year/(.+)' => '?category_name='.$wp_rewrite->preg_index(1).'&year='.$wp_rewrite->preg_index(2),
       );

  // Add the new rewrite rule into the top of the global rules array
  $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}

That should take: http://yourwebsite.com/foobar/year/2011 and return results in category foobar, in 2011.

I'm not sure that structure is the the best way to go about it. To avoid unwanted issues, I would suggest using: http://yourwebsite.com/category/foobar/year/2011 and use instead:

'category/(.+)/year/(.+)' => '?category_name='.$wp_rewrite->preg_index(1).'&year='.$wp_rewrite->preg_index(2)

Hope this helps!


Following the suggestions of @StephenHarris I have developed the code a little further and come up with the following:

add_action('generate_rewrite_rules', 'my_rewrite_rules');
function my_rewrite_rules( $wp_rewrite ) {

    // handles paged/pagination requests
    $new_rules = array('news/(.+)/year/(.+)/page/?([2-9][0-9]*)' => '?category_name='.$wp_rewrite->preg_index(1).'&year='.$wp_rewrite->preg_index(2).'&paged='.$wp_rewrite->preg_index(3));

    // handles standard requests
    $new_rules1 = array('news/(.+)/year/(.+)' => '?category_name='.$wp_rewrite->preg_index(1).'&year='.$wp_rewrite->preg_index(2));

    // Add the new rewrite rule into the top of the global rules array
    $wp_rewrite->rules = $new_rules + $new_rules1 + $wp_rewrite->rules;
}

This allows a site to support URLS that look like:

/news/my-category/year/2011/page/2

as well as

/news/my-category/year/2011

The posts/blog part of my site is prefixed by "news" so you may wish to tweak the first part of the regular expressions and remove the word "news".

If your going to use it make sure you flush your rewrite rules by visiting the permalinks settings page.