Custom URL rewrites in Wordpress — A Getting Started Guide
Hey everyone.
I’ve been tweeting quite a bit recently about custom URL rewrites in Wordpress. After a few hours of trial and error, I’ve managed to get my specific custom URL rewrites working. After reading through several tutorials online (the majority of which used the same examples to explain only a portion the information I was looking for), here’s my tutorial– a getting started guide to Custom URL rewrites in Wordpress.
The process
So, what exactly are we doing here? To put things in point form, this is the process:
- Create custom rewrite rules
- Add our new variables to the public_query_vars array
- Flush (and thus, regenerate) all Wordpress rewrite rules
- Add our functions from steps 1, 2 and 3 into Wordpress via actions and filters
Right, so lets get down to it then.
Create custom rewrite rules
Rewrite rules use a token which is replaced by the necessary query variable. For example, we create a token called %token% which, using a regular expression, gets replaced by “id=”. This will be shown further below.
/**
* create_custom_rewrite_rules()
* Creates the custom rewrite rules.
* return array $rules.
**/
function create_custom_rewrite_rules() {
global $wp_rewrite;
// Define custom rewrite tokens
$rewrite_tag = ‘%exampletag%’;
// Add the rewrite tokens
$wp_rewrite->add_rewrite_tag( $rewrite_tag, ‘(.+?)’, ‘car=’ );
// Define the custom permalink structure
$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 variables to the public_query_vars array
By default, Wordpress has an array of public query variables which can be used within templates and plugins. In order to access our query variables (ie: the “id=” in the above example), the variable needs to be added to the public 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 flushing the rules, we are forcing Wordpress to regenerate it’s rules list, including 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 functions from steps 1, 2 and 3 into Wordpress via actions and filters
Now that our functions have been created, we need to hook them into the various necessary processes within Wordpress. We do this using a combination of actions and filters.
Our first action runs on initialization. This is where we flush the rewrite rules in Wordpress, causing them to be regenerated.
The regeneration brings us to action number 2. This is where we create our custom rewrite rule, hook it on to the global rewrites array and generate the rules.
Our final line is our filter where we add the new public query variable into the global public_query_vars array. We then later use this array to access the variable 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 “%pagename%” is used in place of a specific page slug. To use your rules on only a single page, replace “%pagename%” with a specific page slug. You can either generate this slug dynamically or staticly.
That’s all, folks
And there you have it. A custom rewrite rule in Wordpress. This post is intended as a starting point for using custom rewrite rules in Wordpress. There are virtually infinite possibilities created when using rewrite rules (either one or many) and some really interesting plugins and functionalities can come out of using rewrite rules.
Thanks must also go to Joe Hoyle who’s use of rewrite rules provided the inspiration for this tutorial.
If there’s anything that isn’t clear, please comment below and I’ll do my best to clarify and help.
Before I go… wouldn’t you like the files?
I thought you might. Click below to download the code written above (it’s been written into a class for easy implementation in your projects).
Download the “Custom URL rewrites in Wordpress — A Getting Started Guide” code example.
Great tutorial nd very well-explained. I will definitely find a number of uses for this.
Thanks Justin. I look forward to it.
Please tweet some URLs where you use this tut. I’d be keen to see your implementation of it.
Cheers and thanks again,
Matt.
according to this post (http://wordpress.org/support/topic/226529), flush_rules() is quite expensive and shouldn’t be called on each init. newly generated rules are stored in the database, so you only have to call it once when you introduce new rewrites.
–lite
p.s., i love your blog design!
Hey lite,
Thanks for the link and your very kind comments about my blog design.
I’ll check into flush_rules() and optimise the code accordingly.
Cheers and thanks again,
Matty.
It would be nice if you followed this up with a real plugin 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% certain on that.
Thanks
–Brad
Hi Brad,
Thanks for your comment.
I’ll look into the call to flush_rewrite_rules.
I’ll be writing a few more posts discussing custom rewrite rules in Wordpress, how to work with them and a few advanced uses. These may be followed up with a plugin.
Cheers,
Matt.
The guidance given in the Wordpress Codex is to do it in ‘init’ rather than admin-init’, however I may be not taking into account performance 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 recalculate. You’ll need to do this in your plugin’s init action, so that it happens early enough in the process. ”
Cheers…Dan
@Dan Thanks for your comment, Dan.
I don’t think using ‘init‘ or ‘admin-init‘ makes much of a difference. It means it’ll either run on init only when in the admin area or on init in general. Either way, init happens and the function doesn’t seem very intensive. Using ‘admin-init‘ could possibly increase front-end performance though, as the function would not be running on the front-end. Not sure if the performance difference would be noticeable 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 function will run at the init stage.
Thanks for the link and quote. I find the Wordpress codex to be a useful resource which I use regularly.
Cheers,
Matt.