Beginner's Guide for WordPress - Start your WordPress Blog in minutes.
Choosing the Best
WordPress Hosting
How to Easily
Install WordPress
Recommended
WordPress Plugins
View all Guides

Speed Up Your WordPress by Caching Custom Queries using Transients API

Last updated on by
Follow WPBeginner on YouTube
Speed Up Your WordPress by Caching Custom Queries using Transients API

O boy, the title sounds scary doesn’t it. You have nothing to worry because we will break it all down. Is your theme running custom WordPress queries to show random posts, popular posts, recent posts etc in the sidebar or anywhere else? If yes, then you should consider using the WordPress transient API to cache these queries to reduce resource consumption as well as helping the load time. In this article, we will show you how to speed up your WordPress site by caching custom queries using the Transients API.

Note: You need to understand how WordPress themes work (loops etc), in order for you to follow this post.

So this whole caching and transient lingo is going over my head. Well don’t worry let us explain what it does. Basically if you are running a site like List25 and have a loop that shows 6 random posts in your sidebar, then transient API can help. Every time a user refreshes the page, that custom WP Query that you have will go in your database and pull 6 posts at random. If you are a relatively new site, it shouldn’t be that bad. But if you are getting A LOT of people to your site, then it can crash your SQL server, and you will see the “Error Establishing Database Connection” screen. By adding a few extra lines of code, you can easily store the results of that query (cache it) for a certain period of time using the Transients API.

Example of the loop code that we had for pulling random posts:

<?php $random_query = new WP_Query('orderby=rand&posts_per_page=6');
while ($random_query->have_posts()) : $random_query->the_post();
?>
<div class="gridcontainer">
<div class="gridthumb"><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_post_thumbnail(); ?></a></div>
<div class="gridcontent">
<div class="gridtext"><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></div>
</div>
</div>
<?php endwhile; ?>

The coolest part about our random posts query in the sidebar was it showed new content every time. So by caching the query for 12 hours, we will have the same 6 posts showing for 12 hours right? Well, we found a work around thanks to the suggestion of our friend Konstantin Kovshenin (@kovshenin). He suggested that instead of using WP_Query, we use get_posts and pull 20 posts instead. Cache the results of that query using the transients API, and then use the array_rand() function to show only 6 posts out of the original 20 at random. This way we can keep simulate the random effect on the site.

First thing we did was set the transient. We got the code from the WordPress Codex page.

// Get any existing copy of our transient data
if ( false === ( $special_query_results = get_transient( 'special_query_results' ) ) ) {
    // It wasn't there, so regenerate the data and save the transient
	$randargs = array('orderby' => 'rand', 'numberposts' => 20);
	$special_query_results = get_posts($randargs);
    set_transient( 'special_query_results', $special_query_results, 60*60*12 );
}

Notice the 60*60*12 is the area where you can control the length of the cache. Feel free to change it to whatever you like. Now if we show the $special_query_results using the foreach loop, we will have all 20 posts displayed. So we need to utilize the array_rand() function to only pull 6 items at random. We added the code like this:

$randomposts = get_transient( 'special_query_results' );
$randkey = array_rand( $randomposts, 6 );

Now this will pull out 6 post IDs at random from our transient data. However, it will not pull the values for each post. So we had to do add this bits of code:

$sixposts[0] = $randomposts[$randkey[0]];
$sixposts[1] = $randomposts[$randkey[1]];
$sixposts[2] = $randomposts[$randkey[2]];
$sixposts[3] = $randomposts[$randkey[3]];
$sixposts[4] = $randomposts[$randkey[4]];
$sixposts[5] = $randomposts[$randkey[5]];

Basically we created an array for $sixposts in which we assign a value to each of those items. Not sure if this was the best way of going about it, but it worked. If any of you have better suggestions, then feel free to post it in the comments.

After doing that, we are now ready to display the loop. Simply put the code like this:

global $post; //required for it to work
foreach( $sixposts as $post ) :  setup_postdata($post);

//All the items go here.

endforeach; 

setup_postdata allows you to use all loop tags inside this foreach loop such as the_permalink etc.

To make it easy for everyone, here is the final code that we have:

<?php
// Get any existing copy of our transient data
if ( false === ( $special_query_results = get_transient( 'special_query_results' ) ) ) {
    // It wasn't there, so regenerate the data and save the transient
	$randargs = array('orderby' => 'rand', 'numberposts' => 20);
	$special_query_results = get_posts($randargs);
    set_transient( 'special_query_results', $special_query_results, 60*60*12 );
}

// Use the data like you would have normally...
$randomposts = get_transient( 'special_query_results' );
$randkey = array_rand( $randomposts, 6 );
$sixposts[0] = $randomposts[$randkey[0]];
$sixposts[1] = $randomposts[$randkey[1]];
$sixposts[2] = $randomposts[$randkey[2]];
$sixposts[3] = $randomposts[$randkey[3]];
$sixposts[4] = $randomposts[$randkey[4]];
$sixposts[5] = $randomposts[$randkey[5]];

global $post;
foreach( $sixposts as $post ) :  setup_postdata($post); ?>

<div class="gridcontainer">
<div class="gridthumb"><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_post_thumbnail(); ?></a></div>
<div class="gridcontent">
<div class="gridtext"><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></div>
</div>
</div>

<?php endforeach; ?>

Ta da, now you are only making this DB query once every 12 hours no matter how many users are visiting your site.


Editorial Staff at WPBeginner is a team of WordPress lovers led by Syed Balkhi. Page maintained by Syed Balkhi.

WPBeginner's Video Icon
Our HD-Quality tutorial videos for WordPress Beginners will teach you how to use WordPress to create and manage your own website in about an hour. Get started now »
  • Shasi kanth

    Thanks for sharing this article. Very useful for custom optimization of database queries inside WordPress.

  • Luyen

    Super cool – i’ve always wondered about the transient API, i will definitely use it for future queries.

  • Jean Galea

    I still don’t get why get_posts was used instead of WP_Query, could you expand on that?

    • http://www.wpbeginner.com Editorial Staff

      By using get_posts, we were able to pull 20 random posts from the database and cache the query. Then using the foreach loop, we were able to randomly display 6 out of the 20 posts. Using wp_query, you would have to pull a specific number of posts and display a same number as well.

  • MichealKennedy

    Without this, my Random page generates between 45-49 queries; but with this, it jumps to 56-68 queries. 

  • MichealKennedy

    Man, every plugin should use Transients API! Does WP core make use of this? It should! And have an admin options page built into core to set up cache length and which items to cache, etc. 

  • http://flashkompagniet.dk/ Vayu

    Interesting article, thanks for sharing!
    Why would it be better to use get_post() here rather than WP_Query()?  Just curious that’s all.
    Vayu

    • http://www.wpbeginner.com/ wpbeginner

      Its not better in general. It was better for our case. We are trying to pull 20 posts with get_posts… and then displaying 6 at random. With WP_Query, you will end up displaying all 20.

  • MuhammadWaqas

    lol. this is crazy. a little complex but I will try