Plugin Development

How To Rewrite URLs In WordPress

In this tutorial we are going to look at how you can use the built in WordPress rewriting API to create your own unique links for your website. WordPress will already use this for it's own functionality when you select a new permalink structure.

What Is Rewriting?

URL rewriting is when you change what content is displayed by the server, normally when you type in a URL the web server will simply search for any files in that location. But with rewriting you can still show the same URL but in the back-end change where the server will look for the content. Therefore we can have a URL of /website-1 but tell the server to display content that is located in /website-1/content/index.php

How WordPress Uses Rewrite For Custom URLs

When you go to Settings -> Permalinks, you will need to select how you want your URLs to appear on WordPress. You have many different options to choose from the default WordPress will use is ?p={post_id}, this is the value that is stored in the wp_posts table and what the rewrite API will write to, when it wants to display the post data.

When you select a new permalink structure WordPress will store these rules in the wp_options table so it will know how to search the post table for the correct post. This means that we can have URLs with just the post title in them and WordPress will know that it needs to search on the post_name column to find the correct post to display.

Permalinks

Changing the permalink can change your URLs from

http://www.paulund.co.uk/?p=1

To

http://www.paulund.co.uk/post-title

There are two main benefits of changing the URL structure. One is for SEO reasons, having keywords in the URL give a boost in the rankings as it's a indicator to what the page is about. Another benefit is that it's more user friendly clicking on a link with keywords in the URL.

How Does WordPress Do This?

When you change the permalink structure in WordPress it will make a change the htaccess file which will send all traffic on the website to the index.php file. If you open your htaccess file you will see something similar to this.

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

This will tell the website to send everything to the index.php file, this file will do some checks to work out where the file is that you are trying to access. First it will search to see if the file you want exists in the file structure, if it does it will simply take you to this file. If the file doesn't exist it will need to do some checks to see if it can find the content in the database and will use the rules you setup in the permalink page and the current URL to work it out.

This works fine if you want to use the the default settings with your website but if you want to create your own custom rules then you need to use the built in add_rewrite_rules() function to create a new reg ex pattern of how to rewrite the pages.

Default Rewrite Rules

Below is a list of all the default rewrite rules that you get with WordPress. The first is for the category pages this will allow you to have a URL for the categories of /category/films, there is a /page/ for the pagination on the category pages. The rewrite rule will then rewrite the request to go to index.php?category_name=films so that WordPress displays all the posts that are listed in the category of films.

There is also a tag URL that will work the sameway as the category but will search for all posts that have the tag assigned to them

Next is a date URL that will allow you to search for posts on a specific date by using the URL /2014/03/01 this will search for all posts that were published on the 1st of March 2014.

Finally the last rewrite rule will use the post name and from the URL and search for posts with this name.

category/(.+?)/page/?([0-9]{1,})/?$ => index.php?category_name=$matches[1]&paged=$matches[2]
category/(.+?)/?$ => index.php?category_name=$matches[1]
tag/([^/]+)/?$ => index.php?tag=$matches[1]
page/?([0-9]{1,})/?$ => index.php?&paged=$matches[1]
([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/?$ => index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]
(.+?)(/[0-9]+)?/?$ => index.php?pagename=$matches[1]&page=$matches[2]

Create Your Own Rewrite Rules

In this example we are going to create a rule that will create a url of /actor/%actor-name%, once we get this URL we will pull out the %actor-name% from the URL and search for all posts which have this actor name as a tag attached to the posts.

add_action('init', 'add_actor_url');
function add_actor_url()
{
    add_rewrite_rule(
        '^actor/([^/]*)$',
        'index.php?tag=$matches[1]',
        'top'
    );
}

Now if I was to add a tag onto a post I can search for it by using the /actor/%tag-name% URL, this will display the tag page with all the posts that have this tag attached to them.

You can change these to anything you want, if you want to search on year and get all the posts in this year you can do so easily, you can even use a URL of /iwanttosearchonyearposts/2014.

add_rewrite_rule(
        '^iwanttosearchonyearposts/([^/]*)$',
        'index.php?year=$matches[1]',
        'top'
    );

Create New Query String Parameters

When you create your own rewrite rules they should all be write back to the index.php file, this is where WordPress is instantiated and the database is loaded, there are a number of querystring options you can pass through to the index.php file to get it to process the results and return the correct post. These include postname, category_name, tag, year, monthnum, day, paged.

But if you have created a new post custom meta data and want to have a custom URL to view any post with this meta information then you will need to create your own URL parameters to use on the index.php file. This is where you will need to create your own querystring parameter into the index.php file so that WordPress will understand this parameter and use it in the query variables to use in the WP_Query class.

Using the WordPress function add_rewrite_tag() we can create querystring parameters that WordPress will understand when it processes the query.

To use this function you must pass in the tagname you are going to use and the regex to check this URL matches the rule.

function create_new_url_querystring()
{
    add_rewrite_tag($tagname, $regex, $query);
}
add_action('init', 'create_new_url_querystring');

For example if you have created a custom post meta to store the film year it was produced and you want to create a URL for these posts then you can create a rule with the following.

add_rewrite_tag('%film_year%','([^/]*)');

Now the rewrite tag is setup we can pass in a new parameter of film_year into the index.php file and pick this up in the query_vars() function.

function create_new_url_querystring()
{
    add_rewrite_rule(
        '^film-year/([^/]*)$',
        'index.php?film_year=$matches[1]',
        'top'
    );

    add_rewrite_tag('%film_year%','([^/]*)');
}
add_action('init', 'create_new_url_querystring');

With this now set if we need to get at this information you would use the query_vars() method.

global $wp_query;
$wp_query->query_vars['film_year'];

Or you can use the wrapper function for this which is get_query_var( $querystringParameter ).

$filmYear = get_query_var('film_year');

You will not be able to use the $_GET variable as the current URL will not have any querystrings as we are rewriting this page to the index.php URL.

Once we have that value we can use this to change the query and search for posts that only have this meta information.

Flush Rewrite Rules

When you change your WordPress URL structure or add new rewrite rules then the WordPress database will need to be updated with the new URL rules this is so it will understand how to search for your posts from the given URL.

Sometimes you get the problem of changing a URL structure and WordPress returning a 404 page for your posts. This can be because the rewrite rules have not refreshed correctly.

There are a few ways you can refresh the permalink rules.

First you can navigate to the permalinks page Settings -> Permalinks and change the permalink click the save button, then change it back to the way it was. This will refresh all the rewrite rules on your website and your custom post types should be displayed.

Secondly you can open phpMyAdmin, navigate to the wp_options table and delete the rewrite rules record from this table. Next time WordPress loads it will check for the rewrite rules in this table if they aren't there then it will regenerate the rules.

The third option is to place the function flush_rewrite_rules() under the register rewrite rules. This will completely refresh the rewrite rules and fix any problems with redirecting.

flush_rewrite_rules();
Back to top

Fastest WordPress Hosting With WPEngine

Stunning speed, powerful security, and best-in-class customer service. At WP Engine.

Risk free for 60 days

Comments

  1. David says:

    I have written a plugin featuring rewrite rules that provides additional functionality for our website.

    Unfortunately, when the Yoast SEO plugin updates, it must flush rewrite rules as we suddenly receive 404's. Reactivating my plugin sets the rules again and we are good, until Yoast is updated again.

    Is there a way to prevent the rules from being flushed?