Creating a Rewrite Rule in WordPress

Recently I had to create an endpoint for users to view a dynamically-generated PDF on a site. I wanted to have a nice-looking URL for users. I found it difficult to wrap my head around the process of adding a rewrite rule in WordPress but I finally figured it out.

WordPress offers a function, add_rewrite_rule, to register a rewrite rule for your website. In my example, I am going to set up a rule to handle requests to https://plugins.local/scc-pdf. I am also going to accept two parameters – a value for a record ID I am using to generate the PDF and a unique hash for security so that PDFs cannot be viewed by simply changing the record ID in the URL. The final URL will look similar to:

https://plugins.local/scc-pdf/123/3daf10af8c0db478f95b1e89615a6cc3

In the above example, the record ID will be 123 and the hash is 3daf10af8c0db478f95b1e89615a6cc3. We need to set up a pattern with add_rewrite_rule to look for this type of URL and accept these parameters. I hope you like regular expressions! Luckily, my example will be pretty basic.

I used WordPress’s init hook to register my rewrite rule.

function scc_pdf_rewrite() {
   add_rewrite_rule( '^scc-pdf/([0-9]+)/([A-Z|a-z|0-9]+)/?', 'index.php?recordID=$matches[1]&recordHash=$matches[2]', 'top' );
}
add_action( 'init', 'scc_pdf_rewrite' );

I am starting off my rewrite rule with '^scc-pdf/. In other words, I am looking for a request that begins with scc-pdf/. Then, I am looking for two parameters separated by a forward-slash. These parameters are collected using regular expression patterns.

In my case, the record ID should be a number. The regular expression pattern ([0-9]+) will grab one or more characters matching the [0-9] pattern which means any number. My recordHash parameter is not limited to numbers, though, and can also include text. In this case, the pattern used will be ([A-Z|a-z|0-9]+). This will grab any number of integers or text (either lowercase or capital). Obviously, regular expressions can become very complicated, very quickly. You can test your rewrite rule using the Debug Bar Rewrite Rules WordPress plugin.

Screenshot of using the Debug Bar Rewrite Rules WordPress plugin to test our rewrite rule.
Testing our add_rewrite_rule against https://plugins.local/scc-pdf/123/3daf10af8c0db478f95b1e89615a6cc3

Our URL will be redirected to the index.php file with parameters for recordPDF and recordHash. This is what we want. But if we go to this URL we will not be redirected anywhere. In fact, I just see my test site’s homepage. We need to do two more steps to make this rule active and working.

Note: It is important to mention that you might not always see your changes right away when working with a WordPress rewrite rule. To ensure you are seeing your most recent changes, you might need to flush your permalink rule. Do this by going to Settings > Permalinks and clicking the Save Changes button without changing anything. This will flush the rewrite cache. You may also notice this problem when working with Custom Post Types which also use custom URL structures.

We need to tell WordPress to allow our custom parameters, recordID and recordHash. WordPress has a set of query parameters that it will accept. More information about this can be found at WordPress’s documentation for get_query_var. We can add our parameters to WordPress’s $query_vars by utilizing the query_vars filter. Here is my code for adding the recordID and recordHash parameters to the $query_vars:

function scc_add_pdf_variables( $query_vars ) {
   $query_vars[] = 'recordID';
   $query_vars[] = 'recordHash';
   return $query_vars;
}
add_filter( 'query_vars', 'scc_add_pdf_variables' );

WordPress now can accept my custom query variables and check for their existence. Reloading the URL still doesn’t show a change, though (and, yes, I flushed the permalink cache!). Our last step is to actually handle the redirect. WordPress’s template_redirect hook is a place where we can look for our custom parameters and override WordPress’s default behavior. I’m going to check for these parameters being set and, if they are, do something with them. In my recent project I needed to create a PDF and output it to the browser. For the sake of simplicity I will just show how to access the variables and display them.

function scc_display_pdf() {
   if ( get_query_var( 'recordID' ) && get_query_var( 'recordHash' ) ) {
      echo 'recordID: ' . get_query_var( 'recordID' ) . '<br />';
      echo 'recordHash: ' . get_query_var( 'recordHash' );
      exit;
   }
}
add_action( 'template_redirect', 'scc_display_pdf' );

The get_query_var function can check for our variables. If both the recordID and recordHash are set, I am simply echoing out their values and exiting program execution. Opening my test URL in my browser will echo out the variables:

The query variables, recordID and recordHash.

If these variables are not set WordPress will just keep on running as it normally would and our template_redirect code will have no effect.

Leave a comment

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