in WordPress

Create your own rewrite rules in WordPress

When you write your own WordPress plugin you might need to add new rewrite rules to WordPress. Some people add Rewrite rules direct into htaccess file, but when you open it you can see that WP don’t store rules into this file. All WordPress rewrite rules are stored into the database.

Default WordPress htaccess file


RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

For manipulation with rewrite you can use WP_Rewrite class. It’s functions all listed at the WP Codes, but i will show you how to use most important ones.

rewrite_rules() function

function getRewriteRules() {
    global $wp_rewrite; // Global WP_Rewrite class object
    return=$wp_rewrite->rewrite_rules(); 
}

This function “getRewriteRules”, will return array with listed rewrite rules. Array will be something like …

Array
(
    // ....
    [author/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?author_name=$1&feed=$2
    [author/([^/]+)/(feed|rdf|rss|rss2|atom)/?$] => index.php?author_name=$1&feed=$2
    [author/([^/]+)/page/?([0-9]{1,})/?$] => index.php?author_name=$1&paged=$2
    [author/([^/]+)/?$] => index.php?author_name=$1
    // ...
)


You can use this to check are your rewrite rules inside this array. Only if your rules are listed inside this array your Pretty links will work. Now i will show you how to add your own rewrite rules in WordPress system.

functions add_rewrite_tag and generate_rewrite_rule

function createRewriteRules() {
	global $wp_rewrite;
	
	// add rewrite tokens
	$keytag = '%tag%';
	$wp_rewrite->add_rewrite_tag($keytag, '(.+?)', 'tag=');
	
	$keywords_structure = $wp_rewrite->root . "tag/$keytag/";
	$keywords_rewrite = $wp_rewrite->generate_rewrite_rules($keywords_structure);
	
	$wp_rewrite->rules = $keywords_rewrite + $wp_rewrite->rules;
	return $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'createRewriteRules');

As you can see first we use add_rewrite_tag function to create tag. This function add element to $rewritecode, $rewritereplace and $queryreplace arrays. The second parameter is our rule for this tag, sometimes we want to set tag to accept only numbers, then we will create tag like this one:

	$keytag = '%numtag%';
	$wp_rewrite->add_rewrite_tag($keytag, '([0-9]+)', 'numbertag=');

After tag we created rewrite rule, with link structure we wanted. Function generate_rewrite_rules() just returned array with our rewrite rule, at the end we added our rewrite rules array into WordPress rules array $wp_rewrite->rules.

This function added four rules into WordPress rewrite rules.

    
    [tag/(.+)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?tag=$1&feed=$2
    [tag/(.+)/(feed|rdf|rss|rss2|atom)/?$] => index.php?tag=$1&feed=$2
    [tag/(.+)/page/?([0-9]{1,})/?$] => index.php?tag=$1&paged=$2
    [tag/(.+)/?$] => index.php?tag=$1

Don’t forget to call hook
Hook generate_rewrite_rules is called when you save changes on your permalink structure in admin area. There is other way to call this event. Function flush_rules() will regenerate rewrite rules.

Maybe you didn’t wanted first three rules, right ? There is other way to the the same job, with more control in your hands. You can create this array manual without using generate_rewrite_rules function.

Here is code from some of my new plugin, and you can see how to easily add new rewrite rules with full control.

function add_rewrite_rules( $wp_rewrite ) 
{
        $template_page_name = getTemplatePageName(); // This is my function you can ignore it
	$new_rules = array(
		'('.$template_page_name.')/search/(.*?)/?([0-9]{1,})/?$' => 'index.php?pagename='.
		$wp_rewrite->preg_index(1).'&ypsearch='.
		$wp_rewrite->preg_index(2).'&yppage='.


		$wp_rewrite->preg_index(3),		
		'('.$template_page_name.')/search/(.*?)/?$' => 'index.php?pagename='.
		$wp_rewrite->preg_index(1).'&ypsearch='.
		$wp_rewrite->preg_index(2)
	);
       // Always add your rules to the top, to make sure your rules have priority
	$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'add_rewrite_rules');

Peace of cake, right? In this case you need to do one more thing, add your keys to $public_query_vars variable. As you see we added our rules to rewrite rules array, but we need to add keys to $global $wp_query variable, so lets do it.


function query_vars($public_query_vars) {
	
	$public_query_vars[] = "ypsearch";
	$public_query_vars[] = "yppage";
	
	/*	Note: you do not want to add a variable multiple times.  As in
		the example above, multiple rules can use the same variables 
	*/
	
	return $public_query_vars;
}
add_filter('query_vars', 'query_vars');

Now your new pretty permalinks should work. Now i just want to show you how to get your key values.

    global $wp_query, $wp_rewrite;

    if ($wp_rewrite->using_permalinks()) { // WordPress using Pretty Permalink structure 

        $searchKey = $wp_query->query_vars['ypsearch'];

    } else { // WordPress using default pwrmalink structure like www.site.com/wordpress/?p=123

        $searchKey = $_GET['search']; // now we can get variables from $_GET variable

    }

I show you most important functions you need to know how to use when create new rewrite rules in WordPress, if you want to know more start with WP_Rewrite class.

Write a Comment

Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

30 Comments

  1. Hi.. this is article i m looking for..

    if i have page template named: google.php
    and have navigation/pager with page variabel: “paged”

    can i use your function?
    thanks

  2. Hey nice tutorial ! It helped me to hunderstand rewrite rule in wordpress.
    But it would be very intresting if you can add your getTemplatePageName(); function.

    Thanks

  3. wow thanks for this. I’ve been trying to make pretty links for my plugin and it’s been so frustrating, this clears it up a bit!

  4. Hi, I’m using permalink using /%postname%/.
    I tried to pass variables using wp_redirect as mentioned in the codex but it redirect me at the index.ph instead of staying in the request page.

    Here is the code I use:
    add_filter(‘query_vars’, ‘geotag_queryvars’ );

    function geotag_queryvars( $qvars )
    {
    $qvars[] = ‘geostate’;
    return $qvars;
    }

    add_action(‘init’, ‘geotags_flush_rewrite_rules’);

    function geotags_flush_rewrite_rules()
    {
    global $wp_rewrite;
    $wp_rewrite->flush_rules();
    }

    add_action(‘generate_rewrite_rules’, ‘geotags_add_rewrite_rules’);

    function geotags_add_rewrite_rules( $wp_rewrite )
    {
    $new_rules = array(
    ‘geostate/(.+)’ => ‘geostate=’ .
    $wp_rewrite->preg_index(1) );

    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
    }

    it work when you call http://mydomain.com/myblogfolder/geostate/something

    but it won’t do if i use:
    http://mydomain.com/myblogfolder/mypagepostname/geostate/something

    Do you got any ideas?

    Thanks for all!

  5. Good article, but what would have been better is actually making a simple plugin that showed how to do this for real..

  6. Hi there,

    Thanks for explaining. But i’m still stuck. Can you help me out?

    I am creating a new post type (‘webspots’).
    For this content type i want to create new rewrite rules.

    http://www.example.com/webspots/93/this-is-a-test-title/
    should point to
    http://www.example.com/?post_type=webspot&p=93

    Can you explain me how to do this? I’m stuck for three days now. I researched other people’s plugin codes and read every article about this of the first 3 pages on google. But nowhere is explained on how to create (working!) custom rewrite rules for new post type’s.

  7. I have rewritten rewrite rules in my htaccess in place before the WordPress rewrite.

    I will rewrite /page/page/12345 to /page/page/?num=12345
    Then that is what gets sent to the WordPress rules onto index.php. It works. It is just as if you typed /page/page/?num=12345 into the browser yourself with a $_GET in your template displaying the num.

    Your tutorial is good info though. Cool.

  8. Great article! Your writing is so much better in comparison to most other writers. Thanks for posting when you do, I will be sure to subscribe!

  9. hi,

    I have wordpress installed in the root and I’m trying to incorporate some custom rewrite rules. they look like this:

    RewriteRule ^blog[/]?$ index.php
    RewriteRule ^writing[/]?$ writing.php
    RewriteRule ^art[/]?$ art.php
    RewriteRule ^music[/]?$ music.php
    RewriteRule ^design[/]?$ design.php
    RewriteRule ^animation[/]?$ animation.php
    RewriteRule ^video[/]?$ video.php
    RewriteRule ^contact[/]?$ contact.php

    pretty straight forward stuff. my permalink structure is “/blog/%postname%/” so basically I want website.com/blog to direct to the wordpress home page but instead I get a 404. My other pages seem to work but I get a “page not found” in the page title which is strange.

    Is what I’m trying to do possible?

  10. actually I need to add rewrite rules for the site, I am working on at my work place.

    I am not good with url rewriting and our site is bit complicated, I am using 2 databases, one is wordpress’ own database and other is MSSQL database.

    I want to add some rewrite rule which gains information from MSSQL database, so can you tell me how I can do that?

    Any help would very much appreciated.

    Thanks in advance.
    Arpita

  11. OMG!!! this is awesome explaination 🙂 i ve ever read abt WP rewriting and BTW the site design is simple and pleasing..

  12. Nice post. But I’m wondering about how to auto generate custom permalink for custom post type. Do you have any solution?

  13. Thank you, thank you, thank you! the add_rewrite_rules function example was just what i was looking for, works perfectly and now i can add more custom urls! thanks a lot

  14. I have go through a handful of the content articles on your website now, and I like your style of blogging. I added it to my favorites site collection and will be checking back again in the near future.

  15. Great post, but i just can’t get it to work, pls if you can tell me what i’m doing wrong.
    array looks like:

    [“news/archive/(.+?)/?$”]=>
    string(25) “index.php?d=$1&page_id=84”

    the url index.php?d=2010|08&page_id=84 work fine, but if i put /news/archive/2010|08 i get 404 error.

    pls help, Jernej

  16. Great tutorial.I have a page created in wp named “synonyme”. Now I like to use links like /synonyme/index/K/. I added in .htaccess this rule
    RewriteRule ^synonyme/index/(.*)/$ /synonyme/?index=$1 [L]
    But this does not work. I always get redirected to a post starting with the letter I use in index as value. But I need to go to page synonyme with get parameter “index”. I added in functions.php the code like described above, but it does not work.

  17. Hi,

    Great tutorial, I am hoping you can help me with my issue to clarify what I need to do.

    I have the following code:

    function add_rewrite_rules()
    {
    global $wp_rewrite;
    $new_rules = array(
    ‘([0-9]+)/?$’ => ‘/wp-login.php?action=register&ref=’.$wp_rewrite->preg_index(1),
    ‘([0-9]+)/?$’ => ‘?ref=’.$wp_rewrite->preg_index(2)
    );
    # Always add your rules to the top, to make sure your rules have priority
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
    return $wp_rewrite;
    }
    function add_custom_page_variables($public_query_vars) {
    $public_query_vars[] = “action”;
    $public_query_vars[] = “ref”;
    return $public_query_vars;
    }
    function template_redirect_intercept() {
    global $wp_query;
    $_REQUEST[‘action’] = $wp_query->get(‘action’);
    if ($ref = $wp_query->get(‘ref’)) {
    if(isset($_COOKIE[‘ref’])) {
    setcookie(‘ref’, 0, time()-1, “/”);//Unsetting
    }
    setcookie(‘ref’, $ref, time()+86400*30*3, “/”);//Setting new
    // include(ABSPATH.”/wp-login.php”);
    // exit;
    }
    }

    when I use url like http://www.mysite.com/1 my cookie is set and the page is displayed correctly as long as a ‘static’ home page has not been set, if a ‘static’ page is set in ‘settins/reading’ in WP admin then the returned page is the ‘blog’ page. I think that what I need to do is rewrite URL like http://www.mysite.com/index.php?ref=1 to http://www.mysite.com but I just don’t seem to be getting what I need to do here.

    Can you help point me in the correct direction?

    Thanks!

  18. I’m looking for a solution, no I fould it. Thanks.
    I just have a little question, I see many articles teached us to flush the rewrite rules in hook init, is it required?
    e.g. add_action( ‘init’, ‘flush_rewrite_rules’ );

Webmentions

  • Serve apache 404 for missing assets rather then wp 404 template WP_Rewrites - HelpDesk March 22, 2014

    […] been looking a a lot of examples in and effort to try to achieve this, but they seem inordinately complicated, and not directly applicable. Could someone take a […]

  • Weekly WordPress Review - WPCanada March 22, 2014

    […] Create your own rewrite rules in WordPress (Pro Developer) […]

  • links for 2010-09-15 March 22, 2014

    […] Create your own rewrite rules in WordPress | Pro Developer (tags: wordpress rewrite rules rewriterules webdesign) […]

  • Daily Digest for January 9th | More Than Scratch The Surface March 22, 2014

    […] Shared Create your own rewrite rules in WordPress | Pro Developer. […]