The WordPress Rewrite API

The WordPress Rewrite API

  • Published on: 28th January 2013
  • Author:
  • Under: Other
  • Comments: 7

WordPress has a really useful API called “the rewrite API“. I guess that have already of “url rewriting”, this is the process that makes URLs more readable. For example a url written like this http://mysite.com/?page=12&category=12&author=47 isn’t that good looking. It’s hard to remember it, and search engines don’t like it that much. That’s why nearly every CMS has a builtin function that “rewrites” urls to make them look like this: http://mysite.com/category/business/finance.

The rewrite API and the WP_Rewrite class

Inside WordPress, this process is also known as the permalinks structure. When you switch from the default permalink structure to a custom structure you automatically activate the rewrite API. This is fully automatic. But sometimes you need to create your own custom rewrite rules.

In this post, we are going to create simple functions to create a simple custom rewrite rule. Let’s says we want to get a referrer value, sort of equivalent to a $_GET['referrer'].

If we have a look at the Codex, we can see on the rewrite API page that this API has 6 builtin functions. The most common use of the rewrite is to use these functions, there are plenty of tutorials about that, that’s why i’m going to use filters instead of functions. Because yes, the rewrite API can also be used with filters! Those filters are listed on the WP_Rewrite class Codex page.

Adding a new Query Var

To start, we need to create a function that will tell WordPress that a new rewrite rule is set. This is the job of the add_rewrite_rule() and add_rewrite_tag()  functions, but you can also do it using the query_vars and rewrite_rules_array filters. To do so, we need to create two functions and two filters. The first function is going to simply add a new variable to the query_vars filter, and the second one is going to register this new variable into the global rewrite rules:

/*
|--------------------------------------------------------------------------
| Start Rewrite. Sample: http://mysite.com/referrer/remi
|--------------------------------------------------------------------------
*/

// Register a new var
function rc_add_query_vars( $vars) {
	$vars[] = "referrer"; // name of the var as seen in the URL
return $vars;
}

// Hook our function into query_vars
add_filter('query_vars', 'rc_add_query_vars');

// Add the new rewrite rule to existings ones
function rc_add_rewrite_rules($rules) {
	$new_rules = array('referrer/([^/]+)/?$' => 'index.php?referrer=$matches[1]');
	$rules = $new_rules + $rules;
	return $rules;
}

// Hook the function into rewrite_rules_array
add_filter('rewrite_rules_array', 'rc_add_rewrite_rules');

Once you add this code to any of your plugin file or your theme functions.php file, got to settings > Permalinks, and save the permalinks structure. This action is needed. You should now be able to access your site with this kind or url: http://mysite.com/referrer/your-name. If you want to be redirected on a specific page, change index.php?referrer=$matches[1] by index.php?pagename=my-page&referrer=$matches[1] where “my-page” is the page to be redirected to slug.

Retrieving the variable value

Now that your rewrite rule is set, you might want to access the variable value. But if you do a simple $_GET['referrer'], you won’t get any value. To retrieve the URL vars values, you need to hook a function to the “template_redirect” filter. Hooking to the “init” filter is too early. Then you can access the needed variables through the $wp_query object. Here is a quick sample of how to do it:

// Retrieve URL var
function rc_get_my_vars() {
	global $wp_query;
	
	if(isset($wp_query->query_vars['referrer'])) {
		$referrer = get_query_var('referrer');
	}
}

// Hook the function into template_redirect
add_action( 'template_redirect', 'rc_get_my_vars');

You can next echo the $referrer value or use it as would have done with a normal GET variable.

You can of course modify  use more than one variable:

// in rc_add_query_vars()
$vars[] = "referrer";
$vars[] = "campaign";

// in rc_add_rewrite_rules()
$new_rules = array('referrer/([^/]+)/([^/]+)/?$' => 'index.php?pagename=my-page&referrer=$matches[1]&campaign=$matches[2]');

Don’t forget that you need PHP mod_rewrite module enable to use url rewriting.

Remi
Remi is an expert WordPress developer that coded many great free and premium themes and plugins. His experience on WordPress allows him to produce great stuff and to propose advanced tutorials. (remicorson.com)
Remi
This article has 7 comments
  1. Randy says:

    Nice round up. Are you certain that you can use this in the functions.php file? I seem to recall having trouble doing that. I have only been using this in plugins. The other good thing about using it as a plugin is that you can flush the rewrite rules on activation of the plugin saving you a trip to the permalinks page.

    1. Remi says:

      Hi, if you’re using the template_redirect filter yes you can.

      Author
  2. Rahil Wazir says:

    Hello Remi,
    Thanks for the post.

    I have followed your tutorial everythings working except i cannot able to get the get_query_var(‘referrer’) value. I copied exact code of yours and pasted in functions.php file but didn’t work, also tried pasting your code in sample plugin but that did not work as well. Please tell me what iam doing wrong?

    P,S; I flushed my permalinks each time i made any changes to rewrite rules. And i’m on nginx tried with apache as well :(

  3. Daniel says:

    Hi there,

    I’m wondering if is possible to replace your custom post type slug by a taxonomy term slug. For example:

    My current URL:

    example.com/holiday/remote-brazil

    holiday = CPT

    remote-brazil = CPT item

    I also have a custom taxonomy for that (holiday_category) and custom term (adventures).

    My desired URL is:

    example.com/adventures/remote-brazil

    Any help?

    1. AJ Clarke says:

      So you want the term to become the slug? To be honest I’m not even sure where to start or if it’s even possible because essentially every post could have a different slug depending on what category it’s in. Im not sure if this post will help (I just did a quick Google Search for you) but it seems like it might be a good starting point – http://wordpress.stackexchange.com/questions/39500/how-to-create-a-permalink-structure-with-custom-taxonomies-and-custom-post-types

      Admin

Leave a Reply