Create A Virtual Page Using Rewrite Rules In WordPress

/ Wordpress / by Paul Robinson / 2 Comments
This post was published back on August 8, 2015 and may be outdated. Please use caution when following older tutorials or using older code. After reading be sure to check for newer procedures or updates to code.

In our last tutorial we looked at how to create a endpoint. Those were pages that could be created for each type of permastruct available within WordPress. This time we are going to look at creating a page that does not rely on any of WordPress’ built in permastructs and instead can match any URL you like. I would advise reading the previous tutorial about Endpoints first, if you haven’t already, as this code extends the code used in that tutorial.

Github Repo

If you just want to grab the code & play around then head to Github and clone the repo. It includes the code from both tutorials as I used the same class to keep things simple (since they are related). Check out the readme in the repository for more information.

Adding The Rewrite Rule

Remember we are using our previous class for this tutorial so if you don’t already have the code this will make no sense. Either grab it from the Github repository or go follow the previous Endpoints tutorial first.

To add the rewrite rule is fairly simple. Here is the current code in our rewrite() method.

All we need to do is add an extra line after adding our endpoint. Like this.

What if you don’t want an endpoint too? Then remove the line adding the endpoint, or if you are using this tutorial as reference to write your own code, just don’t add it in.

Now you may be wondering how the function add_rewrite_rule() works? It takes 3 parameters. The first is a regex pattern that explains what you’d like to match. Regex is tricky and it would take a whole new tutorial (in fact probably several) to explain how to write it. Instead the best idea is to search out a few tutorials and use a Regex Tester to make sure your pattern works before using it. Here I’m just using a simple text match, nothing complicated there. If you only want to match a specific slug then you should be fine doing the same.

The second parameter is the URL WordPress should actually fetch. This can be complicated to understand if you don’t know how WordPress’ pretty permalinks work, but to keep things simple let’s say it is where you instruct WordPress what page, post, archive (etc) you want to fetch when this URL is visited. The difference is you use a query string instead of the neat URLs. In this case we want to fetch our custom page so you can use any variable you like here with a 1 as the value. Just remember to keep it URL safe (no spaces, etc).

The final parameter is where in the rewrite rule stack should it be placed. Top will put it at the top and cause your rule to be matched before any of WordPress’ defaults when there is a conflict of rules. Bottom will put it at the bottom and will cause WordPress’ default rules to be matched over your rule if there is a conflict.

Query Variables

The variable we added in the second parameter of the add_rewrite_rule() function is called a query variable & we must tell WordPress we have added it or it will cause problems later. To do this we need to add another action to our __construct() in the class. Like this.

You can see that we have a new add_action() call. This hooks the query_vars() method, that we will create next, to run when the query_vars action is called via WordPress.

The code for the query_vars() method looks like this.

We simple append the query variable we used in the rewrite rule and return it. Be warned. If you do not return the $vars variable at the end of the method things will break pretty badly since it will not give all the normal query variables back to WordPress.

Adding Template Loading

Technically that’s all there is to it. Deactivate & reactivate the plugin, or save the permalinks page (to flush rewrite rules) and the page will be available. However because we aren’t telling WordPress what to do when that page is loaded it will just load the home page. So to fix that in your change_template() method add a little code to load something special.

Then create a template file, in the templates folder of your plugin folder or in your theme folder, called template-vptutorial.php and place what you like in there. Remember to add get_header() and get_footer() if you want the rest of your theme to load. You can also use the example I placed in the Github Repository for this tutorial. Again for simplicities sake it is compatible with twentyfifteen.

Frequently Asked Questions

Can I change the name of the templates?
Of course. Name them whatever you like. Just remember to change the path/name in the change_template() method.

Can I match a dynamic URL variable in the rewrite rule?
Yes. Just use a regex rule that matches what you’d like, for example ([0-9]+) for a number and then use $matches[1] to output the value in the second parameter. For example.

Note that the in the $matches array the matches from the regex pattern start at 1 not 0.

That’s it. If you have any questions, problems or you notice a mistake please let me know in the comments & I’ll get back to you as soon as I can.


Author’s gravatar

I think that the add_action( 'query_vars', array( $this, 'query_vars' ) ); line should instead read add_filter( 'query_vars', array( $this, 'query_vars' ) ); . According to the Developer Reference, it’s a filter hook, not an action hook.

Author’s gravatar author

Hey Patrick,

Your right it is a filter. What is really weird is that it still works (I’ve just cloned the github repo which has the same typo). That being the case I’m not sure why that filter is needed. I always thought it was required to get WordPress to whitelist URL variables for use in URL rewriting.

I’ve changed it in the tutorial anyway and will push a change to the github repo to make sure anyone cloning that doesn’t have the same issue.

Thanks for pointing it out.

Older Comments
Newer Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

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

I'll keep your WordPress site up-to-date and working to its best.

Find out more