WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to filter posts in a category by the year of the post's date. I also want to do this without being redirected to the year template so my ideal URL would be http://example.com/category/reports/2011/ which would load the template file category.php where I could then use query_posts to include only the posts that were published in 2011 and are in the reports category.

Here is my rewrite rule code...

function filter_category_by_year_rewrite_rules( $wp_rewrite ) {
    /* Creates rewrite rules for filtering category archives by year (/category/reports/2011/)*/
    $new_rules = array(
        "category/(.+?)/(\d\d\d\d)/?$" => "index.php?category_name=" . $wp_rewrite->preg_index(1) . "&year=" . $wp_rewrite->preg_index(2)
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
add_action('generate_rewrite_rules', 'filter_category_by_year_rewrite_rules');

My problem is WordPress automatically redirects index.php?category_name=reports&year=2011 to /category/reports/ with no trace of the year parameter. How can I intercept this redirect?

I tried hooking in to the template_redirect action to no avail :(

function testing_redirect() {
    global $wp;
    if($wp->request['matched_rule'] == 'category/(.+?)/(\d\d\d\d)/?$') {
        load_template( 'category.php' ); //TEMPLATEPATH .'/category.php';
add_action('template_redirect', 'testing_redirect', 1);
share|improve this question
up vote 4 down vote accepted

This should work:

add_action( 'init', 'wpa12742_init' );

function wpa12742_init(){
  add_rewrite_rule( 'category/(.+?)/(\d{4})/?$', 'index.php?category_name=$matches[1]&year=$matches[2]', 'top' );
  add_rewrite_rule( 'category/(.+?)/(\d{4})/page/(\d+)/?$', 'index.php?category_name=$matches[1]&year=$matches[2]&paged=$matches[3]', 'top' );


On second thought, that's not enough, since you'll get caught by redirect_canonical().

Add this too:

add_filter( 'term_link', 'wpa12743_term_link', 10, 3 );

function wpa12743_term_link( $link, $term, $taxonomy ){
  if('category' != $taxonomy && !preg_match( '@^\d{4}$@', get_query_var('year') ) )
    return $link;
  return trailingslashit( $link ) . get_query_var( 'year' );
share|improve this answer
You're right, canonical_redirect was the problem. See my answer below this one for how I solved it. Did you mean to filter term_link and not redirect_canonical? I kind of like you're way better for the trailing slash. – kingkool68 Mar 22 '11 at 19:16
Cool! I did mean to filter term link, but your method works just fine. :) – John P Bloch Mar 22 '11 at 19:35

Ahhh redirect_canonical was the culprit. Here's how I weeded this bugger out...

function kill_canonical_redirect($redirect_url, $requested_url) {
    global $wp;
    if($wp->matched_rule == 'category/(.+?)/(\d\d\d\d)/?$') { 
        return false;
    } else {
        return $redirect_url;
add_filter('redirect_canonical', 'kill_canonical_redirect', 10, 2);

Basically I look at the rewrite rule that matched the page request and if it is the one I wrote then I know I can kill the canonical redirect by simply returning false.

Perhaps the more helpful info for anyone reading over this is how I figured this out. I installed the Better HTTP Redirects plugin ( http://hakre.wordpress.com/2011/03/20/how-to-debug-redirect-problems-in-wordpress/ ) which has a really handy redirect debugging tool when WP_DEBUG is set to true in wp-config.php.

From there I realized the redirect was being triggered from Line 367 of /wp-includes/canonical.php so after looking at the source code on Trac ( http://core.trac.wordpress.org/browser/trunk/wp-includes/canonical.php#L367 ), I figured out how to kill the canonical redirect.

share|improve this answer
A really really crazy good tool for looking through core is PHPXref: phpxref.ftwr.co.uk/wordpress/nav.html – John P Bloch Mar 22 '11 at 19:36
+1 The canonical redirects were really annoying me until I found this. Thanks! – Marcus Downing May 20 '11 at 9:35

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.