Custom URL rewrites in WordPress — A Getting Started Guide

Digg Muti Delicious

Hey every­one.
I’ve been tweet­ing quite a bit recently about cus­tom URL rewrites in WordPress. After a few hours of trial and error, I’ve man­aged to get my spe­cific cus­tom URL rewrites work­ing. After read­ing through sev­eral tutori­als online (the major­ity of which used the same examples to explain only a por­tion the inform­a­tion I was look­ing for), here’s my tutorial– a get­ting star­ted guide to Custom URL rewrites in WordPress.

The pro­cess

So, what exactly are we doing here? To put things in point form, this is the process:

  1. Create cus­tom rewrite rules
  2. Add our new vari­ables to the public_​query_​vars array
  3. Flush (and thus, regen­er­ate) all WordPress rewrite rules
  4. Add our func­tions from steps 1, 2 and 3 into WordPress via actions and filters

Right, so lets get down to it then.

Create cus­tom rewrite rules

Rewrite rules use a  token which is replaced by the neces­sary query vari­able. For example, we cre­ate a token called %token% which, using a reg­u­lar expres­sion, gets replaced by “id=”. This will be shown fur­ther below.

/​**
* create_​custom_​rewrite_​rules()
* Creates the cus­tom rewrite rules.
* return array $rules.
**/

func­tion create_​custom_​rewrite_​rules() {
global $wp_​rewrite;

/​/​ Define cus­tom rewrite tokens
$rewrite_​tag = ‘%exampletag%’;

/​/​ Add the rewrite tokens
$wp_rewrite->add_rewrite_tag( $rewrite_​tag, ‘(.+?)’, ‘car=’ );

/​/​ Define the cus­tom permalink struc­ture
$rewrite_​keywords_​structure = $wp_rewrite->root . “%pagename%/$rewrite_tag/”;
/​/​ $rewrite_​keywords_​structure = $wp_rewrite->root . “$slug/$rewrite_tag/”;

/​/​ Generate the rewrite rules
$new_​rule = $wp_rewrite->generate_rewrite_rules( $rewrite_​keywords_​structure );

/​/​ Add the new rewrite rule into the global rules array
$wp_rewrite->rules = $new_​rule + $wp_rewrite->rules;

return $wp_rewrite->rules;

} /​/​ End create_​custom_​rewrite_​rules()

Add our new vari­ables to the public_​query_​vars array

By default, WordPress has an array of pub­lic query vari­ables which can be used within tem­plates and plu­gins. In order to access our query vari­ables (ie: the “id=” in the above example), the vari­able needs to be added to the pub­lic query vars array.

/**
* add_custom_page_variables()
* Add the custom token as an allowed query variable.
* return array $public_query_vars.
**/

function add_custom_page_variables( $public_query_vars ) {
$public_query_vars[] = 'car';

return $public_query_vars;

} // End add_custom_page_variables()

Flush all WordPress rewrite rules

By flush­ing the rules, we are for­cing WordPress to regen­er­ate it’s rules list, includ­ing our new rules in the rules set.

/**
* flush_rewrite_rules()
* Flush the rewrite rules, which forces the regeneration with new rules.
* return void.
**/

function flush_rewrite_rules() {

global $wp_rewrite;

$wp_rewrite->flush_rules();

} // End flush_rewrite_rules()

Add our func­tions from steps 1, 2 and 3 into WordPress via actions and filters

Now that our func­tions have been cre­ated, we need to hook them into the vari­ous neces­sary pro­cesses within WordPress. We do this using a com­bin­a­tion of actions and filters.

Our first action runs on ini­tial­iz­a­tion. This is where we flush the rewrite rules in WordPress, caus­ing them to be regenerated.

The regen­er­a­tion brings us to action num­ber 2. This is where we cre­ate our cus­tom rewrite rule, hook it on to the global rewrites array and gen­er­ate the rules.

Our final line is our fil­ter where we add the new pub­lic query vari­able into the global public_​query_​vars array. We then later use this array to access the vari­able in our theme.

add_action( 'init', 'flush_rewrite_rules' );
add_action( 'generate_rewrite_rules', 'create_custom_rewrite_rules' );
add_filter( 'query_vars', 'add_custom_page_variables' );

The scope of rewrite rules

By default, WordPress rules are applied across all pages. Thus, the tag “%page­name%” is used in place of a spe­cific page slug. To use your rules on only a single page, replace “%page­name%” with a spe­cific page slug. You can either gen­er­ate this slug dynam­ic­ally or staticly.

That’s all, folks

And there you have it. A cus­tom rewrite rule in WordPress. This post is inten­ded as a start­ing point for using cus­tom rewrite rules in WordPress. There are vir­tu­ally infin­ite pos­sib­il­it­ies cre­ated when using rewrite rules (either one or many) and some really inter­est­ing plu­gins and func­tion­al­it­ies can come out of using rewrite rules.

Thanks must also go to Joe Hoyle who’s use of rewrite rules provided the inspir­a­tion for this tutorial.

If there’s any­thing that isn’t clear, please com­ment below and I’ll do my best to cla­rify and help.

Before I go… wouldn’t you like the files?

I thought you might. Click below to down­load the code writ­ten above (it’s been writ­ten into a class for easy imple­ment­a­tion in your projects).

Download the  “Custom URL rewrites in WordPress — A Getting Started Guide” code example.

Related Posts

8 Comments

  1. Posted 7th November, 2009 at 1:34 pm (300 days ago)

    Great tutorial nd very well-​​explained. I will def­in­itely find a num­ber of uses for this.

    • Posted 7th November, 2009 at 1:38 pm (300 days ago) in reply to Justin Slack

      Thanks Justin. I look for­ward to it. :)

      Please tweet some URLs where you use this tut. I’d be keen to see your imple­ment­a­tion of it. :)

      Cheers and thanks again,
      Matt.

  2. litemotiv's Gravatarlitemotiv
    Posted 26th November, 2009 at 10:13 pm (281 days ago)

    accord­ing to this post (http://wordpress.org/support/topic/226529), flush_​rules() is quite expens­ive and shouldn’t be called on each init. newly gen­er­ated rules are stored in the data­base, so you only have to call it once when you intro­duce new rewrites.

    –lite

    p.s., i love your blog design!

    • Posted 27th November, 2009 at 8:07 am (280 days ago) in reply to litemotiv

      Hey lite,
      Thanks for the link and your very kind com­ments about my blog design. :)

      I’ll check into flush_​rules() and optim­ise the code accordingly.

      Cheers and thanks again,
      Matty.

  3. Posted 16th December, 2009 at 2:25 am (261 days ago)

    It would be nice if you fol­lowed this up with a real plu­gin example, and I “think” the add_​action( ‘init’, ‘flush_​rewrite_​rules’ ); needs to be add_​action( ‘admin-​​init’, ‘flush_​rewrite_​rules’ ); BUT I am not 100% cer­tain on that.

    Thanks

    –Brad

    • Posted 19th December, 2009 at 8:54 am (258 days ago) in reply to Brad

      Hi Brad,
      Thanks for your comment.

      I’ll look into the call to flush_​rewrite_​rules.

      I’ll be writ­ing a few more posts dis­cuss­ing cus­tom rewrite rules in WordPress, how to work with them and a few advanced uses. These may be fol­lowed up with a plu­gin. ;)

      Cheers,
      Matt.

  4. Posted 18th January, 2010 at 7:25 pm (228 days ago)

    The guid­ance given in the WordPress Codex is to do it in ‘init’ rather than admin-​​init’, how­ever I may be not tak­ing into account per­form­ance with this.

    From: http://codex.wordpress.org/Query_Overview:

    “So if you want to modify rewrite rules, you will need to call $wp_rewrite->flush_rules() to force them to recal­cu­late. You’ll need to do this in your plugin’s init action, so that it hap­pens early enough in the process. ”

    Cheers…Dan

    • Posted 24th January, 2010 at 11:36 am (222 days ago) in reply to Dan Smart

      @Dan Thanks for your com­ment, Dan. :)

      I don’t think using ‘init‘ or ‘admin-​​init‘ makes much of a dif­fer­ence. It means it’ll either run on init only when in the admin area or on init in gen­eral. Either way, init hap­pens and the func­tion doesn’t seem very intens­ive. Using ‘admin-​​init‘ could pos­sibly increase front-​​end per­form­ance though, as the func­tion would not be run­ning on the front-​​end. Not sure if the per­form­ance dif­fer­ence would be notice­able though.

      It looks, to me, like it’s a case of 6 of 1 or half a dozen of the other. Using either method, the func­tion will run at the init stage. :)

      Thanks for the link and quote. I find the WordPress codex to be a use­ful resource which I use reg­u­larly. :)

      Cheers,
      Matt.

Leave your comment

Your email is never shared. Required fields are marked *

*
*