I found the WordPress documentation about custom rewrite rules pretty confusing and most of the blog posts / Stackoverflow posts I could find weren’t much better. Silly thing is it’s actually pretty simple to set up your own rewrite rules when you know how. Here’s what I figured out:
- You want to create your rewrite rules on the WordPress
initaction hook AND the plugin
- You should also flush your rewrite rules after creating them in the
- You also need to create custom “rewrite_tags” to access route parameters in the
- The rewrite rule seemingly has to point to
index.php, so you have to use GET parameters instead of using pretty links in the rule.
- Pretty permalinks must already be enabled!
- Flushing the rules on the
deactivationhook doesn’t seem to do much good!
So let’s look at an example, we want to have a page called
items that’s controlled by our code. We also want to make it so that a user can view any item by browsing to a URL like
/items/view/14 and the code needs to be able to access the item ID.
Put that in your plugins directory - call it
example.php - and then activate the Example plugin from wp-admin. You should see in the frontend that a page
/items has been created, and if you browse to
/items/view/1324 it will display 1324 back to you. Deactivate the plugin and the page will be deleted and things will mostly be cleaned up.
Now, this example’s not perfect; deactivation of the plugin does not flush away our rewrite rule! Why?! Well, as the init function is called before the plugin is deactivated, the rule is already in memory when the rules are flushed. I’m not sure the best way to overcome that, although I don’t think it’s the most significant issue as the next time the rules are flushed by WordPress or a plugin our old rule will be removed. (Hint you can browse to the permalinks page in wp-admin to flush your rewrite rules.)
Why do we have to create our rewrite rules from both the
init hook and
activation hook? Well, it appears that the
init hook is not called until after the plugin is activated, but we can only flush on activation. So to have our rules work, we must create them at activation. But if something else flushes the rules, and we haven’t created them beforehand they’ll be removed, so we need to create them each time at activation just in case! So the only way to cover all bases appears to be to create the rewrite rules on both init and activation!
OK, but what’s with the rewrite tags? Honestly, I have no idea, but if you don’t jump through that hoop
get_query_var doesn’t return them, and FYI
$_REQUEST doesn’t contain them either.
Finally I’d like to draw attention to the second parameter of our add_rewrite_rule call:
'index.php?pagename=items&itemid=$matches'. Originally I tried something like
items/?itemid=$matches but that does not work, you have to make sure it’s in terms of index.php. A bit confusing to start with but not a problem, you can do everything you need to that way using GET parameters like
Hope that helps! Dave.