WordPress transients, like most things in programming, are about being lazy. Unfortunately, in this case it isn’t about making the programmers life easier but rather about making the web server’s life easier (and the people who maintain and pay for the web server).
What is the temperature outside?
When someone asks what is the temperature outside, it takes so effort to get the answer. You need to:
- stand up
- walk to the window
- look at the thermometer outside
- walk back
- tell the person the answer
While these steps are relatively trivial, they still take effort and a non-zero amount of time. If one minute later someone asks you the temperature outside, you wouldn’t repeat these steps. You would use the temperature you remember from one minute ago.
In computer science, this idea is called caching. Instead of doing the work to find the answer each time, we re-use an answer we already figured out.
Finding the Temperature with the Dark Sky API
The Dark Sky API, allows you to retrieve weather conditions (after you sign up for a free API key) for a specific latitude and longitude as a JSON response (which is a format that is easy for a computer to understand).
I’ve written some code to retrieve the current temperature in Lehigh Valley and display it in a WordPress widget. This code works by loading the data from the Dark Sky API. We don’t want to call the Dark Sky API each time we display the temperature, in the same way we don’t want to go look at the thermometer outside the window each time we want to know the temperature.
Technical Reasons to Cache the Temperature
In regards to our website there are two concrete reasons we don’t want to repeat the process of looking up the temperature from the Dark Sky API.
- The Dark Sky API has a limit of
1,000
free lookups per day, any more than that would incur a charge - It takes time to contact the Dark Sky API, which slows how fast our page loads
Code to Cache the Temperature
In my code, there is a function called fe_get_lv_temp_f()
, which returns the current temperature in Lehigh Valley in degrees Fahrenheit. This function does this task by calling fe_get_lv_temp_api_call()
, which makes the actual call to the Dark Sky API.
function fe_get_lv_temp_f() {
// This is a remote HTTP request, it is SLOW!
$temp = fe_get_lv_temp_api_call();
return $temp;
}
Refactor to cache the temperature
We’re going to modify this function to cache the temperature. To do this, we’ll use two WordPress functions:
set_transient()
This function stores our value (in this case the temperature in the variable $temp
) under the label $transient_key
for a maximum of $max_time
seconds.
set_transient(
$transient_key, // Label of where to store the value.
$value, // Value to cache.
$max_time // Max time in seconds to keep.
);
WordPress set_transient() documentation
get_transient()
This function retrieves the value stored under the label $transient_key
and returns it. In the case that no value is currently stored there, the value false
is returned instead.
get_transient( $transient_key );
WordPress get_transient() documentation
Updated Code
function fe_get_lv_temp_f() {
// Try to retrieve the value stored as the transient 'fe_lv_temp'
$temp = get_transient( 'fe_lv_temp' );
if ( false !== $temp ) {
// We have a cached value (the transient).
// Use it and do NOT process any other lines in this function.
return $temp;
}
/**
* If we reach this point, we do not have a cached value that we can use.
* Get get the current temperature by calling the Dark Sky API.
*/
// This is a remote HTTP request, it is SLOW!
$temp = fe_get_lv_temp_api_call();
// Store the temperature in a transient,
// so we can use it in the future without making the API call.
set_transient(
'fe_lv_temp', // Label of where to store the value.
$temp, // The value to cache.
1800 // The maximum number of seconds to store (i.e. 30 minutes)
);
return $temp;
}
When I Use Transients
- For remote API calls
- For slow database queries
When I Don’t Use Transients
I do not use transients if I can not recreate the data. There is no guarantee that a transient will be stored for its maximum amount of time. Transients can be deleted by WordPress any time after they are created (but will be deleted no later than the maximum number of seconds set when using set_transient()
).
Whether or not you use a transient is not based on how long the value is stored, it is based on doing things faster than could have been done a slower way.
Another Example of Using Transients
The WordPress Top Tags Plugin displays the top tags used in the blog and the first 10 posts under each of the tags. This involves a lot of database querying, so I’ve added a transient to store the output.
Outdated Information (a.k.a. stale data)
In the Top Tags plugin, I’m caching the result for 86400
seconds (24 hours). Unfortunately this means if a new post is added or tags changed, the information we display could be outdated for up to 24 hours. Instead, we want to add code to delete the transient if the data changes.
In the plugin I’m listening for changes to any of the posts by using the save_posts
WordPress hook. When this action occurs, I check if it is a post
that was saved (not a nav_menu_item
, attachment
, or other post type). If it is a post
, we delete the transient (so we’re not displaying stale data).
add_action( 'save_post', 'fe_tts_clear_transient', 10, 2 );
function fe_tts_clear_transient( $post_id, $post ) {
if ( $post && 'post' === $post->post_type ) {
delete_transient( 'fe_tts_output' );
}
}
Other Transient Tips
Use WordPress Time Constants
Looking at 1800 seconds
, it is not immediately obvious to some of us that this is 30 minutes
. To help clarify these values, we can use some of WordPress’s built-in time constants.
e.g. instead of 1800
seconds, we can write 30 * MINUTE_IN_SECONDS
See Easier Expression of Time Constants for more information
Store data rather than output
Tom J. Nowell does a great job clarifying the benefits of returning data rather than HTML. Along with this idea, storing data in your transients rather than HTML will have the same benefits.
You may have noticed in the WordPress Top Tags Plugin, I did not follow this guideline. In this particular instance, I felt caching the HTML markup provided a simpler example for an introduction to transients.
Clean Up After Yourself
If you’re using a transient in a plugin you write, consider deleting the transient on plugin deactivation. This prevents a orphaned transient from cluttering up your database after the plugin is deactivated. Thanks to Kevin Cristiano for this tip. I wrote a blog post specifically about Deleting Transients on Plugin Deactivation that covers more of the details and rational.
Advanced Techniques
Mark Jaquith’s library TLC Transients adds enhancements to WordPress’s transients, in the form of two improvements:
- support for soft-expiration (use old content until new content is available)
- background updating of the transients (without having to wait for a cron job)
My advice is if you’re new to transients, start by using the built-in WordPress transients (which will provide a significant gain). Once you’re comfortable with WordPress’s transients and ready to strech yourself, then I would investigate TLC Transients.
Resources
- Getting Started with Transients Slides from my WordCamp Lehigh Valley 2017 talk
- Top Tags WordPress Plugin code
- Lehigh Valley Current Temp Widget WordPress Plugin code
- WordPress set_transient() documentation
- WordPress get_transient() documentation
- WordPress delete_transient() documentation
- WordPress time constants
- Dark Sky API
- Return Data not HTML post
- TLC Transients code
- Query Monitor Plugin a tool for tracking page render time and database queries
- Transients Manager Plugin a tool for modifying and deleting stored transients
Photo Credit
heartlover1717 on flickr
Sal, I heard you speak at WordCamp Lehigh Valley last year on transients. It was the best talk of the day IMHO. I was doing some custom plugin development tonight that desperately needed some transients and I came right to this blog post. Thanks for sharing your knowledge.