The Transients API provides a great tool for caching data that needs to be refreshed regularly. In most cases it makes it easy for developers to improve the performance of their themes/plugins, yet there are situations which display weaknesses in the Transients API.
When your transient is storing external data, like news from the BBC News API, the HTTP request required to refresh the data can significantly delay the page rendering. We are going to go through an example of how we can get around this weakness and refresh our transient without delaying the page rendering.
Does it really matter?
Lane Joplin recently discussed the importance of page load speed here on Torque, but will refreshing a transient really make a difference? In most cases normal usage of transients is fine, but in situations where refreshing the data involves a significant amount of time (like HTTP requests) it can seriously delay the page rendering and create a bad experience for the viewer.
In a recent project refreshing Tweets from the Twitter API delayed page rendering by over half a second. As a developer this is the last thing I want to do to, so I began looking into what I could do about it.
What can we do?
What we need is the ability to get the old data from a transient and identify it needs to be refreshed. Then we can show the current user slightly old data and refresh the transient after the page has rendered.
After looking at how the Transients API manages the expiry and discovering the shutdown hook, which has turned out to be incredibly useful, I was ready to begin. I am going to use a working example using the BBC News API to show a list of the latest headlines.
You can see the full code example in this Github Gist, and I will now go through it and breakdown how it works. This first function manages fetching data from the BBC News API and storing it in a transient, along with a custom expiry time:
The code above gets interesting where (at line 16) we add a custom expiry time to the data to be stored in the transient, for 5 minutes into the future. Then later (line 19) set the transient as normal with a much longer expire time. This allows us to refresh the data every 5 minutes while always getting the data returned from the transient.
You are free to set the transient’s expire time to anything you like, I keep it at 24 hours to remind me that it is not a permanent store and I should not treat it as such.
This next function manages fetching the contents of the transient, refreshing immediately if it has expired or checking our custom expiry time if it returns data. This allows use of the data stored in the transient and the ability to check the custom expiry time to decide if we need to refresh the data.
The second if statement (line 18) is where this gets interesting. If the transient returns data then we check to see if the current timestamp is greater than the custom expiry timestamp we added to the transient data. If true we know we should refresh the transients after the page has been rendered.
We do this by attaching the ‘pb_refresh_news’ function (the first function we saw) to the ‘shutdown’ hook. This hook is incredibly useful as it fires after the page has rendered just before PHP shuts down.
Now there is just one last task remaining, to fetch and use the data for display in a template file.
This is a very basic example of how you can then use these functions to handle the output of the data. Importantly the call to ‘pb_get_news’ (line 9) handles fetching and where appropriate refreshing of the data. Again, you can get all the code in one go from the Github Gist.
I have used fetching the BBC News headlines as an example, but this technique is valuable in many different scenarios (like integrating with social media APIs). It is also worth mentioning that the ‘shutdown’ hook is valuable in other situations too, including when using WP Cron. Many cron tasks will not need to be performed before page load, so you can make good use of the ‘shutdown’ hook there too.
The above code can be improved in many ways and was designed solely to illustrate the technique.
If you know of any other ways to use the Transients API or the ‘shutdown’ hook I would love to hear about them in the comments.
Peter Booker enjoys coding, business and philosophy. He loves bringing these together to create things which people love to use. You can find out more on his website.
Join the conversation