Hijacking the URL for filtering

Right, here’s the deal. I’ve got a loop of which displays news posts, these posts can belong to special categories (not normal categories) and I want to be able to filter by them.

If I wasn’t too interested in aesthetics I’d use a link like this:

domain.com/news?filter=cat1

But instead what I want to do is this (» rewritten):

domain.com/news/cat1 » domain.com/news/?filter=cat1

I’ve modified the .htaccess to pass the cat1 value as a GET variable:

RewriteEngine On
RewriteBase /
RewriteRule ^news/(.*)/$ /news/?filter=$1 [L,QSA]

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

The problem is even though this is now successfully passing the filter variable in, WordPress treats the /cat1/ as a page, it obviously cannot find it and thus throws a 404.

Is there a way to allow this particular URL rewriting without WordPress firing a 404? It appears it’s taking the URL in the address bar and parsing that, what I really want is for it to parse the rewritten URL.

Thanks

1 Answer
1

WordPress also has a rewriting mechanism, it’s better to use that instead of doing it in the .htaccess file.

You can add your own rewrite rules to it. In your case we want to store the cat1 part in a separate query variable, so we also need to tell WordPress to allow this query variable (it uses a whitelist for safety).

The precise form of the rewrite rule depends on what http://domain.com/news/ is: is it a Page with a custom template, or something else? You should find this out (using my Rewrite analyzer plugin for example), and add this to the rewrite rule.

add_action( 'init', 'wpse16819_init' );
function wpse16819_init()
{
    // Base form, will probably not work because it does nothing with the `news` part
    add_rewrite_rule( 'news/([^/]+)/?$', 'index.php?wpse16819_filter=$matches[1]', 'top' );
    // Use this instead if `news` is a page
    add_rewrite_rule( 'news/([^/]+)/?$', 'index.php?wpse16819_filter=$matches[1]&pagename=news', 'top' );
}

add_filter( 'query_vars', 'wpse16819_query_vars' );
function wpse16819_query_vars( $query_vars )
{
    $query_vars[] = 'wpse16819_filter';
    return $query_vars;
}

Remember to flush the rewrite rules (save them to the database) after you add this code. You can do this by visting the Permalinks page in the admin area.

You can now access the wpse16819_filter variable with get_query_var( 'wpse16819_filter' );.

Leave a Comment