Caching data with WordPress Transients API

Before start about WordPress Transients API, lets talk about the meaning on Transients. It means somethings staying in a place for only a short time. In our case, we can tell store data in database only for short period of time.

Using WordPress Transients API, we can use wp_options database table to temporarily store cached information in a simple and standardized way by giving a custom name and a time frame after which it will expire and be deleted.

Transients API is very similar to the Options API but the different is it added feature of an expiration time.

So anyone who needs to cache specific data but wants it to be refreshed within a given time frame, they can use WordPress Transients API.

We can use a set of Transients API functions to store and retrieve information from database.

Set/Get Transient:

  • set_transient()
  • get_transient()
  • set_site_transient()
  • get_site_transient()

Delete Transient:

  • delete_transient()
  • delete_site_transient()

The “site_” functions are work network wide when using WordPress Multisite.

Lets see how can we save and fetch Transients and where we can use it with an real example:

Before go to the example, we need to understand about the parameters of set_transient() API function.

set_transient( $transient, $value, $expiration );

You can see more details about parameters here.

Now lets see a real example where we can use WordPress Transients API.

Suppose you have a website build with WordPress. In your home page, there is a section which showing the 5 latest articles. We can do query like this :

$args = array(
	'post_type' => 'post',
	'post_status' => 'publish',
	'posts_per_page'=> 5,
);

$latest_articles = new WP_Query( $args );

// The Loop
if ( $latest_articles->have_posts() ) {
	echo '<ul>';
	while ( $latest_articles->have_posts() ) {
		$latest_articles->the_post();
		echo '<li>' . get_the_title() . '</li>';
	}
	echo '</ul>';
} else {
	// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();

Can you understand, when we are browsing home page, every time the above query build and executing on database to fetch latest posts even if you add a new article every 5 years. Is it not a wrong way to fetch latest posts? Is it not make your site slow?

WordPress Transients API comes to solve this problem. We can save the above query in our wp_options table for a certain period of time and can call it from wp_options table when need like below:

if ( false === ( $latest_articles = get_transient( 'wa_latest_articles' ) ) ) {
	$latest_articles = new WP_Query(
		array(
			'post_type' => 'post',
			'post_status' => 'publish',
			'posts_per_page'=> 5,
		)
	);

	// Put the results in a transient. Expire after 1 week.
	set_transient( 'wa_latest_articles', $latest_articles, WEEK_IN_SECONDS );
}

if ( $latest_articles->have_posts() ) {
	echo '<ul>';
	while ( $latest_articles->have_posts() ) {
		$latest_articles->the_post();
		echo '<li>' . get_the_title() . '</li>';
	}
	echo '</ul>';
} else {
	// no posts found
}
wp_reset_postdata();

Here WEEK_IN_SECONDS is a time constants. In WordPress 3.5, several constants were introduced to easily express time:

MINUTE_IN_SECONDS  = 60 (seconds)
HOUR_IN_SECONDS    = 60 * MINUTE_IN_SECONDS
DAY_IN_SECONDS     = 24 * HOUR_IN_SECONDS
WEEK_IN_SECONDS    = 7 * DAY_IN_SECONDS
MONTH_IN_SECONDS   = 30 * DAY_IN_SECONDS
YEAR_IN_SECONDS    = 365 * DAY_IN_SECONDS

Here there is a problem with expiration time. Can you see, i set the expiration time is 1 week. This would be appropriate if you really don’t care if your new article shows up a week after you add it to your site.

If you want to making sure that the article shows up immediately then i suggest adding a large expiration time( YEAR_IN_SECONDS ). Then create a function to flush your transient when a new article is published.

add_action( 'publish_post', 'wa_flush_latest_articles_transient' );

function wa_flush_latest_articles_transient( $post_id, $post ){
	delete_transient( 'wa_latest_articles' );
}

Leave a Reply

Your email address will not be published. Required fields are marked *