Preventing index.php?category_name=something from redirecting

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…

Read More
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/(.+?)/(dddd)/?$" => "index.php?category_name=" . $wp_rewrite->preg_index(1) . "&year=" . $wp_rewrite->preg_index(2)
    );
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
    var_dump($wp_rewrite);
}
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/(.+?)/(dddd)/?$') {
        load_template( 'category.php' ); //TEMPLATEPATH .'/category.php';
    }
}
add_action('template_redirect', 'testing_redirect', 1);

Related posts

Leave a Reply

2 comments

  1. 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' );
    }
    

    EDIT

    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' );
    }
    
  2. 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/(.+?)/(dddd)/?$') { 
            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.