When it comes to building web applications, one of the most important things that we have to constantly be mindful of is performance.
As they say, performance is a feature.
And regardless of if you're a designer, developer, or a user, you know this intuitively to be true: When it comes to applications, we hate waiting. We get frustrated when things don't perform fast enough, or we have to wait longer than we believe that we should.
To that end, most modern web development frameworks make it possible to implement some type of caching through the use of certain APIs, and WordPress—though a foundation—is no different.
So as we continue our discussion on why WordPress is a viable option for serving as a foundation in web application development, we'll take a look at the APIs that are provided by the core application, how they work, how we can leverage them to our advantage, and how performance can be enhanced even more by additional caching plugins.
Why Is Caching Important?
In short, caching is important because it allows us to store data that is frequently retrieved in a place in memory so that it can be quickly retrieved.
When you look at this at a larger scale, this becomes increasingly evident when multiple users are viewing a site. By that, I mean that if a single person—or a very small number of people—hit a website, and the site has its data stored in a database, then each time a page is loaded, then that information must be retrieved from the database, inserted into the page, and then returned to the user.
If a level of caching is instituted, then calls to the database won't have to be made as frequently. Instead, the information can be pulled from an area in memory that results in faster retrieval, and thus faster page load times.
We'll get into the technical details of this a bit more later in the article.
What About Plugins?
If you've been using WordPress for a significant amount of time, then you're likely familiar with a number of caching plugins that are available.
These are no doubt great solutions to speeding up your web site and/or web application, but it does raise the question: If plugins are available to do this, then why should we worry about it?
It's a valid question, to be sure, but the plugins can only do so much work on their own.
Developers can structure their applications in such a way that they not only perform well without caching mechanisms, but will also be greatly enhanced by said caching plugins.
By that, I mean that these caching plugins look for data to be stored in a certain location by themes and applications, and if we can programmatically do that within the context of our own work, then the plugins will result in even greater performance.
After we take a look at the APIs that we have available, we'll revisit this topic to see how they enhance performance of caching plugins later in the article.
The Transients API
In order to introduce a our first level of caching into the application, we need to take advantage of WordPress' Transients API. First, note that the official definition of the a transient is "something that exists only for a short amount of time."
Just as defined in the Codex:
[The Transient API] offers a simple and standardized way of storing cached data in the database temporarily by giving it a custom name and a timeframe after which it will expire and be deleted.
But what does this mean exactly? After all, the data is still being stored in the database, so why is this any better than keeping data stored in any other database table (such as the wp_options
table?)?
Once we revisit the discussion on caching and plugins, we'll talk more about this in more detail.
Setting Transients
Setting a transient value is actually really easy, and it's much like storing data in the options table.
Specifically, you need a key value that will uniquely identify the data, and then you need a value to be associated with that key. You also need an expiration time (in seconds) to keep the data in the table before refreshing it.
So let's say that we want to store the current user's name as the last—or most recent—user active on the site. We can do this by taking advantage of the wp_get_current_user()
function.
First, we'll set the value like this:
set_transient( 'most_recent_user', wp_get_current_user()->user_login, 12 * HOUR_IN_SECONDS )
Here, notice a couple of things:
- I'm identifying the most recent user in the system as the current user who was logged in, and we're storing it for 12 hours.
- Note that the
HOUR_IN_SECONDS
constants is something that was introduced in WordPress 3.5. A full list of the constants are available here.
Though this is how we go about setting a transient, this still doesn't account for how we can manage transients if they don't exist, or if they already exist.
We'll cover that more a bit later in the article.
Retrieving Transients
When it comes to retrieving transients, it's very similar to retrieving things such as meta data or options. By that, I mean that we simply need to know the key by which to retrieve the information.
So in keeping consistent with the example above, we can retrieve the most recent user of the application with the following call:
get_transient( 'most_recent_user' );
This will obviously return whatever type of information that you stored, or if the transient has expired—that is, over 12 hours have passed—then the function will return the boolean value of FALSE
.
This is key to remember especially when you're attempting to read cache values, and then needing to grab them from another data source should they not be available in the transient store.
We'll take a look at a complete example of doing this before the end of the article.
Deleting Transients
Finally, should you need to delete a transient either to remove it completely it, or to remove it before its defined expiration in order to replace it with another value, then you'd simply use the following function:
delete_transient( 'most_recent_user' );
Additionally, this function will return FALSE
if the deletion of the transient value is not successful; otherwise, it will return FALSE
.
Expiring Transients
When it comes to setting times for cache values to expire, there are a number of ways that make it easier to set values rather than music basic integer manipulation.
For example, MINUTE_IN_SECONDS
is much easier to use than 60 especially when multiplying it by, say, minutes, hours, or days.
And as of WordPress 3.5, several constants have been added to the core application that make these calculations much easier to read.
Namely:
MINUTE_IN_SECONDS
HOUR_IN_SECONDS
DAY_IN_SECONDS
WEEK_IN_SECONDS
YEAR_IN_SECONDS
Much easier to use, to read, and to write, isn't it?
A Complete Example of Using Transients
At this point, I think it's important to look at how we can go about setting up transients start with storing a value in the options table.
Here's the order in which we'll go about doing this:
- We'll save an option in the
wp_options
table. - Next, we'll check to see if the value exists in the cache.
- If the value does exist in the cache, we will delete it; otherwise, we will add it.
Then, in the second half of the code, we'll do the following:
- We'll try to retrieve a value function the cache.
- If the value exists in the cache, we'll fall back to the options table; however, if the value does exist, then we'll use it.
With that said, let's take a look:
$username = wp_get_current_user()->user_name; add_option( 'most_recent_user', $username ); // Check to see if the value exists in the cache if ( FALSE !== get_transient( 'most_recent_user' ) ) { // If it does, we'll delete it... if( delete_transient( 'most_recent_user' ) ) { // ...and store the most recent user for a maximum of one minute set_transient( 'most_recent_user', MINUTE_IN_SECONDS ); } else { // The deletion was unsuccessful, so log the error } } // Now try to read the value from the cache. if ( FALSE !== ( $username = get_transient( 'most_recent_user' ) ) { // Since it doesn't exist, then we'll read it from the option's table $username = get_option( 'most_recent_user' ); // And then we'll update the cache set_transient( 'most_recent_user', $username, MINUTE_IN_SECONDS ); }
Note that this example is not complete—it could be refactored to be a bit cleaner, and the code should be abstracted into functions that are more relevant to the application, but the purpose of this code is to show how to handle conditional logic, options, and transients.
How Does This Fit With Plugins?
Now, with all of that said, we can revisit the question as to how using transients can improve performance within plugins.
As we previously mentioned:
After we take a look at the APIs that we have available, we'll revisit this topic to see how they enhance performance of caching plugins later in the article.
With that said, caching and the WordPress database has to do with the location of the data in the database.
Since transients are stored in a separate location than the rest of the data, plugins—such as a memcached-based plugin, for example—will look for data where transients are stored, then load the data into memory from that location.
Thus, when the data is requested, it will be retrieved from memory. If the data doesn't exist, then it will be retrieved from the database.
On top of that, if the programming is done correctly, when data fails to be read from the cache and is retrieved from the database, it will be inserted back into the cache so that the next time it is retrieved it will be available in memory.
Finally, the key thing to note about transient information is that it has a period of expiration. This means that data will only be stored in this area of the database for a specific amount of time.
To that end, we need to account for that. This means that whenever we're looking to retrieve transients, we need to make sure they exist. If they don't, then we'll pull them from where they are located, and then store them in the proper location.
Custom Queries
At this point, we've covered a lot of ground of the features that WordPress offers as it relates to a foundation for web application development.
But we've got one last major component to cover and that's how to deal with custom queries.
Sure, there are some great APIs as it relates to running queries designed for WordPress specific purposes—like WP_Query
and WP_User_Query
, but we'll also take a look at some of the native facilities that allow us to write custom queries against the database using defined WordPress objects as well as methods that allow for proper data sanitization.
But we'll cover all of that and more of that material in the next article.
Comments