URL rewrites and pagination

The question:

I must say that I am a complete nooby at WordPress custom URL rewrites. I have searched for past many days to find a clear explanation of how to determine and write correct pattern for URL rewrites. I have a custom page template that uses query var passed to it, e.g. http://example.com/pagename?user=username. In this “pagename” refers to the custom page template and “user” refers to the custom query var. I need this to be represented using the URL http://example.com/pagename/username.

I also require the above to work with pagination. So http://example.com/pagename/username/page/2 should be able to represent http://example.com/pagename/page/2?user=username

It would be great if someone can provide me with a working example and an explanation of how I should determine and write correct pattern for URL rewrites.


The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Extending @Stephen Harris’ excellent answer, I would opt for;

add_action( 'generate_rewrite_rules', 'my_rewrite_rules' );
function my_rewrite_rules( $wp_rewrite )
    $wp_rewrite->rules = array(
        'mypageslug/([^/]+)/page/?([0-9]{1,})/?$' => $wp_rewrite->index . '?pagename=mypageslug&user=' . $wp_rewrite->preg_index( 1 ) . '&paged=' . $wp_rewrite->preg_index( 2 ),
        'mypageslug/([^/]+)/?$' => $wp_rewrite->index . '?pagename=mypageslug&user=' . $wp_rewrite->preg_index( 1 )

    ) + $wp_rewrite->rules;

This follows the defacto regex standard used in WordPress core. The main change from Stephen’s code sample is the use of $wp_rewrite->index to ensure the rewrite is passed through to WordPress (otherwise it may get added to the ‘external’rewrite list).

Secondly, and most importantly, passing the pagename var in the query string – this means WordPress will behave as if it were ordinarily loading a page with the slug mypageslug.

UPDATE: I forgot to add, make sure user is a public query var, otherwise WordPress won’t map it from the URL. Either filter it in with query_vars or add it using the global $wp;

add_filter( 'query_vars', 'my_query_vars' );
function my_query_vars( $vars )
    $vars[] = 'user';

// my preferred method - make sure you run this only after 'init' has fired!
$GLOBALS['wp']->add_query_var( 'user' );

// then once the request has been parsed (anything after the action 'parse_request')
$user = get_query_var( 'user' );

Method 2

I have had a similar problem and successfully solved it. In fact I recently wrote this blog post which used this solution.

WordPress uses rules to make the URls pretty, the idea is to use a filter to call a function that add rules (then after going to settings > Permalinks and clicking save the rules should be added). This is the code:

add_action('generate_rewrite_rules', 'my_rewrite_rules');
function my_rewrite_rules( $wp_rewrite ) {
  $new_rules = array(
     'pagename/(.+)' => 'pagename?user='.$wp_rewrite->preg_index(1),

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

The idea is that WordPress checks to see if the url is of the form www.example.com/pagename/something and uses that something to set the user variable.

To get pagination to work you’ll need to add the following rule to the $new_rules array – above the rule already there (this is because WordPress checks the rules in order).

    'pagename/(.+)/page/?([0-9]{1,})' => 'pagename?user='.$wp_rewrite->preg_index(1).'&paged='.$wp_rewrite->preg_index(2),

Similarly this checks for www.example.com/pagename/something/page/2 say and interprets this as example.com/pagename?user=username&paged=2. (Paged is the query variable recognised by WordPress for determining the page in pagination).

Hope this helps!

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment