WordPress Transients API is very powerful tool which allows temporary storing data in wp-options table. It is very similar to WordPress Options, but has an expiration time, which enables us to use it as a caching engine.
The best thing about WordPress Transients is that they are inherently sped up by caching plugins, where normal options are not. A memcached plugin, for example, would make WordPress store transient values in fast memory instead of in the database.
For this reason, transients should be used to store any data that is expected to expire, or which can expire at any time. Transients should also never be assumed to be in the database, since they may not be stored there at all.
Using the API is very simple, there are only 3 methods that can be used:
Table of Contents
Saving Transients
For saving transients we are using set_transients method, which accept three parameters:
- $transient a unique identifier for your cached data
- $value Data to save, either a regular variable or an array/object. The API will handle serialization of complex data for you.
- $expiration Number of seconds to keep the data before refreshing.
Example (this example is storing data for 3 minutes):
[code lang=”php”]
set_transient(‘transientKey’, ‘transientValue’, 60*3);
[/code]
Getting Transients
For retrieving the data stored using Transients API, we are using the method get_transients which expects only Transient key as a parameter.
Example:
[code lang=”php”]
get_transient(‘transientKey’);
[/code]
Deleting Transients
For deleting Transients data we should use delete_transient method with Transient key as a parameter.
Example:
[code lang=”php”]
delete_transient(‘transientKey’);
[/code]
Using WordPress Transients to cache remotely fetched data
Imagine a scenario where we must fetch last 50 Tweets from Twitter and show them on WordPress page. Normally, you would cache this Tweets in a file, but why not use powerful Transients instead.
This code is responsible for fetching my last 50 tweets:
[code lang=”php”]
function transientsTest()
{
// setting some parameters
$username = ‘codeforest’;
$maxTweets = 50;
$url = ‘http://api.twitter.com/1/statuses/user_timeline.json?screen_name=’ . $username . ‘&count=’ . $maxTweets;
timer_start();
// getting the tweets
$tweets = curlRequest($url);
$tweets = json_decode($tweets);
echo ‘
- ‘;
- ‘ . $tweet->text . ‘
- No tweets
if (count($tweets)) {
foreach ($tweets as $tweet) {
echo ‘
‘;
}
} else {
echo ‘
‘;
}
echo ‘
‘;
timer_stop(1); echo ‘ seconds’;
}
function curlRequest($url) {
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
return $response;
}
[/code]
As you can see, this code will go to Twitter every time we refresh the page on which we are showing this Tweets. I am using timer_start and timer_stop functions to measure the time that is needed.
After 500 times I got an average of 1.2 seconds for this operation. That is just not acceptable.
Now, lets make use of the Transients and see what happens:
[code lang=”php”]
function transientsTest()
{
// setting some parameters
$username = ‘codeforest’;
$maxTweets = 50;
$url = ‘http://api.twitter.com/1/statuses/user_timeline.json?screen_name=’ . $username . ‘&count=’ . $maxTweets;
timer_start();
$tweets = get_transient(‘cfTweets’);
if (false === $tweets) {
// getting the tweets
$tweets = curlRequest($url);
// put it in transients
set_transient(‘cfTweets’, $tweets, 60*3);
}
$tweets = json_decode($tweets);
echo ‘
- ‘;
- ‘ . $tweet->text . ‘
- No tweets
if (count($tweets)) {
foreach ($tweets as $tweet) {
echo ‘
‘;
}
} else {
echo ‘
‘;
}
echo ‘
‘;
timer_stop(1); echo ‘ seconds’;
}
[/code]
I am showing just the main function. My timer is staying at 0.003 seconds. Now, that is a big difference.
You would say that this is normal because it is very expensive to fetch data from another server. Let see some other examples.
Caching WordPress menu using Transients API
So we have a big menu with sub menus and everything. I used a simple wp_nav_menu function to render this menu. When not cached, it takes 1 second on average to load the menu.
Let’s put it in the cache:
[code lang=”php”]
function getThemesMenu()
{
$menu = get_transient(‘cfMenu’);
if (false === $menu) {
// parameter echo will return the menu instead of echoing it
$menu = wp_nav_menu( array( ‘theme_location’ => ‘primary’, ‘echo’ => 0 ) );
set_transient(‘cfMenu’, $menu, 60*3);
}
return $menu;
}
[/code]
Benchmark shows that now it takes 0.005 seconds to retrieve and render the menu. That is really a huge difference.
But, we must clear this cache after the menu is saved, so that the changes are reflected on the site immediately. It is quite simple, just put this code in theme’s functions.php file:
[code lang=”php”]
function updateMenu()
{
delete_transient(‘cfMenu’);
}
add_action( ‘wp_update_nav_menu’, ‘updateMenu’ );
[/code]
And that’s it. Now, transient will be cleared every time you save your menu.
Caching complex query results using WordPress Transients API
We can have quite complex queries in our WordPress site. General example for storing them using Transients:
[code lang=”php”]
function getComplexData()
{
if (false === ($data = get_transient(‘cfData’))) {
$query = “SELECT wposts.*,
wpostmeta.meta_value AS some_status,
wpostmeta2.meta_value AS some_rating
FROM {$wpdb->posts} AS wposts,
{$wpdb->postmeta} AS wpostmeta,
{$wpdb->postmeta} AS wpostmeta2
WHERE wposts.ID = wpostmeta.post_id
AND wposts.ID = wpostmeta2.post_id
AND wpostmeta.meta_key = ‘status’
AND wpostmeta2.meta_key = ‘average_rate’
AND wposts.post_type = ‘event’
AND wposts.post_status = ‘publish’
ORDER BY some_status ASC,
some_rating DESC
LIMIT $offset, $per_page
;”;
$data = $wpdb->get_results($query);
// store it for 24 hours
set_transient(‘cfData’, $data, 60*60*24);
}
return $data;
}
[/code]
This query took around 0.5 seconds without cache and 0.006 seconds with Tranisents cache.
It is important to clear the transient data every time data changes in the database!
Conclusion
Big performance gains can be achieved with WordPress Transients API. If you use it together with memcached engine, that the gain would be even more impresive.
Are you using Transients or plan to use it? Share your thoughts below in the comments section.
Nice article! I didn’t think that transients can speed up basic stuff like menu generation.
Thanks for the comment.
Basically, if you have a lot of complex queries, Transients API is the first step of optimization. You can later install memcached and put Transients data in it.
Excellent post. Transients are EXACTLY what I need to cache API request. You got me kick started in the right direction. I’ve heard a lot about transients at WordCamps and they’re great from what I can tell so far. How long should we store transient data for? How long is too long?
Pingback: Caché de datos en Wordpress (I): Transients API
Great posts, I know this post is old but it is still gold. Thanks.
Comments are closed.