Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

Using WordPress For Web Application Development: Available Features, Part 6: URL Rewriting (or Routes)

by

One of the nicest things about modern web application development frameworks is that they provide a way to generate really clean routes—or URL schemes—that map to the conceptual model of how the application is structured.

For instance, given some type of data—say, an Individual—you may be able to perform the following actions:

  • add
  • update
  • delete

And so on.

Depending on the nature of your application, you may be able to do more (such as, say, add a spouse), but for the purposes of this post, the basic CRUD operations suffice to demonstrate the point.

For those of you who have been following along, we've been taking a look at a variety of features that WordPress offers as a foundation for application development. In continuing this discussion, it's important that we take a look at the APIs that are available for us to customize WordPress' rewrite rules.

The average user is likely familiar with how to change the URL schema within the WordPress dashboard—which we'll briefly discuss to make sure we're all on the same page—however, there are far more capabilities available to those that understand URL rewriting in WordPress.

In fact, we have the ability to construct URL rewrite rules to match and perform just like those of modern MVC-based frameworks.


Understanding Rewrite Rules

To make sure that we're all on the same page, rewrite rules can be thought of as the way that a certain pattern is matched against the webserver to retrieve data from the database.

For example, in the standard WordPress installation, the default permalink structure is like this:

http://domain.com/?p=123

This URL includes a query string parameter—namely the key value pair of p=123 which, in the context of WordPress, is saying "retrieve the post with the ID of 123".

If you take a deeper look at the options on the Permalink Settings screen, you'll also see a variety of options:

Permalinks

Another example of the rewrite rules that you're likely to see are what are known as "pretty permalinks" or, as named in the WordPress dashboard, "Post Name".

In this format, the URL looks like this:

http://domain.com/post-title/

From here, the requested URL comes into the web server and then, based on a set of rules, determines the ID of the post having that title and returns it to the requesting client (which would be the browser).

Between these two examples, there's a basic principle in play that demonstrates exactly what rewrite rules are.

In short, rewrite rules define a set of rules in which in the incoming URL is translated into a format that retrieves information from the database for the client.

Of course, this raises two questions:

  1. How are rewrite rules generated?
  2. And, perhaps more importantly, why are they so complicated?

The Business of Rewrite Rules

The reason that rewrite rules can serve as a bit of a challenge for developers is because they are based around regular expressions. And there's an old quote about regular expressions by Jamie Zawinski:

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

Funny, but true. And that's why dealing with custom rewrite rules in WordPress can be such a challenge for many developers.

Unfortunately, we can't demonstrate every variation or type of URL schema that can be created or supported by rewrite rules, but we can take a look at a couple of practical examples that show how to get started and provide a foundation or a guide for what we would need to do in future work with our applications.

Flushing Rewrite Rules

One thing that is important to note is that when you define your rewrite rules, they won't immediately take effect—they have be flushed. This means that you need to erase the old set of rules, to replace them with the new set of rules.

There are two ways that you can go about doing this:

  1. You can click on Save Changes in the Permalink Settings dashboard. Despite the fact than an option will be selected, whatever you've defined in your application's functions.php file will be used.
  2. You can make a call to $wp_rewrite->flush_rules(); and programmatically take care of the problem.

Regardless of the route that you choose, it's important to remember this step because each time you define a new rewrite rule, you'll need to flush the old rules.

How Does the Rewrite API Work?

When it comes actually writing our own rewrite rules, it's important to understand how the Rewrite API works.

It can be distilled into a four-step process:

  1. A URL is requested from the web server.
  2. If content exists at the requested URL, then the content will be returned (this can be an image, a font, or whatever).
  3. If the content doesn't exist, then the request will be directed to index.php which will match the pattern of the URL.
  4. The content will then be returned from WordPress to the requesting client.

If you're interested in seeing the definition of rewrite rules based on the configuration that you have in the Permalink dashboard, check out the Rewrite Rules Inspector plugin.

This plugin will render a list of all the rules that are currently in place to match specified URL schemas, complete with the regular expressions and the matched variables against index.php.

Rewrite Rules Inspector

Make sense? If not, let's take a look at a couple of simple, practical examples.

An Example of Rewriting Rules

Given that we know that patterns will be matched and passed through to index.php, we can take advantage of the add_rewrite_rule function to define how our custom URLs will work.

A Short Title for a Post ID

Let's say that we're looking at the first post in the system—that is, we're looking at the post with the ID of 1.

In most vanilla WordPress installations, this is Hello World and the URL is usually http://domain.com/hello-world or http://domain.com/?p=1 depending on your permalink settings (that is, your current set of rewrite rules).

But let's define a rule such that http://domain.com/first will also load the first post in the database:

function example_add_rewrite_rules() {

	add_rewrite_rule( 'first', 'index.php?p=1', 'top' );
	flush_rewrite_rules();

}
add_action( 'init', 'example_add_rewrite_rules' );

Let's add one more rule that will follow suit and allow us to load the second post in the database. Namely, http://domain.com/?p=2.

function example_add_rewrite_rules() {

	add_rewrite_rule( 'first', 'index.php?p=1', 'top' );
	add_rewrite_rule( 'second', 'index.php?p=2', 'top' );

	flush_rewrite_rules();

}
add_action( 'init', 'example_add_rewrite_rules' );

Assuming that you've read the documentation for add_rewrite rule, this is easy enough to understand, right?

In short, it takes in three arguments:

  • The first argument is a regular expression to match against the requested URL. In our case, we're using simple words.
  • The second argument is the URL to actually fetch. Again, in our case, we're retrieving the first and second posts, respectively.
  • Finally, the last argument is the priority, which can be "top" or "bottom". If set as "top", then this rule will be evaluated above all other rules; however, if "bottom", then it will be evaluated last.

Now, these examples are basic. This isn't enough to really show us how to set up custom routes such as those that we outlined earlier in this article. To do that we need to take a look at some more complex expressions.

Import Notes About Flushing Rewrite Rules

But before we go about doing that, it's important to note that calling flush_rewrite_rules() like we're doing above is actually a bad practice. It works in the example above, but it can actually slow down a site's load time.

In fact, it really only needs to be called whenever the rewrite rules change. This may occur whenever a plugin is activated, or it may change when a theme is activated.

Whatever the case, make sure that you properly hook your functions so that rewrite rules aren't flushed on every single page load—just whenever the rewrite rules themselves have changed.


A More Complicated Approach to Rewrite Rules

In order to introduce a more complicated set of rewrite rules like those that we detailed earlier in this post from CRUD operations, it's important to understand the following two functions:

  • add_rewrite_tag will let WordPress know of custom query string variables. This is also used in conjunction with the next function.
  • add_rewrite_rule, as mentioned, will allow us to add additional rewrite rules to WordPress (as well as set their priority).

Now let's say that we have a custom post type called Individual that represents a person in the application. Then, let us say that the Individual also has the following methods and corresponding URLs available:

  • all: http://domain.com/individuals/
  • update: http://domain.com/individual/update/1 which is used to update the first person
  • deletehttp://domain.com/individual/delete/1 which is used to delete the first person

So the schema is simple enough, but how do we go about implementing it?

First, we need to define the rewrite rules:

function example_add_rewrite_rules() {

	// Define the tag for the individual ID
	add_rewrite_tag( '%individual_id%', '([0-9]*)' );

	// Define the rules for each of the individuals
	add_rewrite_rule( '^individual/update/([0-9]*)', 'index.php?individual=update&individual_id=$matches[1]', 'top' );
	add_rewrite_rule( '^individual/delete/([0-9]*)', 'index.php?individual=delete&individual_id=$matches[1]', 'top' );

}
add_action( 'init', 'example_add_rewrite_rules' );

Next, we need to define these custom functions for each individual so that they update the proper record in the database when called.

In this case, we'll define two functions—one for updating the Individual and one for deleting the Individual. The following code also assumes that a bit of information is going to be contained within the form being submitted from the browser.

Specifically, it assumes that the Individual ID, first name, last name, and other information will be sent in order to update the individual.

function example_process_individual( $input ) {

	if ( example_updating_user() ) {
		example_update_individual( $input );
	} else if ( 'true' == $input['delete_individual'] ) {
		example_delete_individual( $input['individual_id'] );
	}

}
if( ! is_admin() ) add_action( 'init', 'example_process_individual' );

function example_update_individual( $input ) {

	/* The incoming $input collection from an assumed form
	 * that will be used to update the user.
	 *
	 * It may include information such as the ID, the first name,
	 * last name, and so on.
	 *
	 * Upon success, use <code>wp_redirect</code> to go back to the homepage,  or reload
	 * the page to show an error.
	 */

}

function example_delete_individual( $individual_id ) {

	/* Use the incoming ID to locate the individual record and remove it
	 * from the database.
	 *
	 * Upon success, use <code>wp_redirect</code> to go back to the homepage,  or reload
	 * the page to show an error.
	 */

}

function example_updating_user() {
	return 0 == strpos( $_SERVER['REQUEST_URI'], '/individual/update' );
}

function example_deleting_user() {
	return 0 == strpos( $_SERVER['REQUEST_URI'], '/individual/delete' );
}

Notice above that the first function is hooked into the init action and is only fired if the user is not logged in as an administrator. This could be enhanced furthermore by conditionally setting it to load only if it's coming from a certain page; however, for this example, it serves its purpose.

Next, read the code comments for the Update and the Delete functions to see how they should function.

Finally, note that the final two functions are simple helpers meant to allow us to write cleaner code in the initial hooked function.

A Bit Incomplete

I know—this is a bit of an incomplete example, but for a lengthy article, and a complex topic, I've aimed to do the best I can to showcase the WordPress Rewrite API, discuss the advantages of using it, and talk about how it can be used to create cleaner URL routes.

The truth is, it's still somewhat of a challenging topic and is one that's best grasped through implementation. Nonetheless, this yet another component of the WordPress application that allows it to serve as a foundation for web application development.


Up Next

With all of that said, it's time to move on to the concept of caching.

Sure, there are a lot of caching plugins that are available for WordPress, but if you're a developer, you're looking to build in a level of native caching, and you're looking to leverage WordPress APIs to do so. If that's the case, it's important to familiarize yourself with what's available and how to do it.

So with that said, we'll next turn our attention to the Transients API so that we can handle a bit of native caching on our own, and review how this can help third-party caching mechanisms make our applications even faster.

Advertisement