There's a cool (and underused by plugins) API in WordPress: the Transients API. Transients are temporary options, ie options set with an expiration time. Anytime you're storing options and they have a short life span, you should use transients instead.
Disclaimer: I, for one, am totally underusing this API too, as it is rather new (it was introduced in WP 2.8) and I didn't update my plugins which could use it. Hopefully if you learn anything in this article, you will update your code :)
Transients functions
Basically transients are options, so their API is very similar to the Options API. The three functions you'll want to use are: set_transient(), get_transient(), delete_transient().
- // Save a transient to the DB
- set_transient( $transient_name, $transient_value, $expiration );
- // Get value of a transient from the DB
- $value = get_transient( $transient_name );
- // Delete a transient from the DB
- delete_transient( $transient_name );
Things to do or know:
- Let WP do the dirty job: don't escape things for SQL, don't serialize arrays
- Give your transients unique and self explanatory names. Prefix them just as anything else.
- When you get_transient() and it has expired or has never been set before, the function returns false
- In case you want to manually check the DB, saving a transient named 'ozh' adds two entries in the option table: _transient_ozh storing the value, and _transient_timeout_ozh with the Unix timestamp of the expiration date
- Transients don't clutter the DB: when you fetch a transient value, if it has expired it is removed from the database
Using transients: an example
Let's make a simple plugin that displays the IPs of our last 10 visitors: this value is by essence temporary, and we will store it in a transient with a 3 minutes expiration.
The plugin will do the following:
- Store last 10 visitors' IPs in an array
- Get visitor's IP and check if it's in the array already
This whole simple plugin is just one function:
- // Get visitor IP, update and return list
- function wp_ozh_slvc() {
- $ip = $_SERVER['REMOTE_ADDR'];
- $visitor_ips = get_transient( 'ozh_livecounter' );
- if( false == $visitor_ips OR !in_array( $ip, $visitor_ips ) ) {
- // our transient has expired (or has never been set) or doesn't contain this IP
- $visitor_ips[] = $ip;
- // just keep at most last ten entries
- if( count( $visitor_ips ) > 10 )
- array_shift( $visitor_ips );
- // store this transient with a 3 minutes expiration
- set_transient( 'ozh_livecounter', $visitor_ips, 60*3 );
- }
- return join( ', ', $visitor_ips );
- }
And that's it. Now in a template PHP file such as sidebar.php just use the following:
- <?php echo 'Currently online: '.wp_ozh_slvc(); ?>
(save as .php then put in your plugins folder)
As you can see the plugin is as basic and simple as it can be. Pushing things further you would widgetize the output for easier integration into themes, make smarter IP detection to check proxies and filter search engine robots out, implement a country detector based on the IP and display cute tiny flags, add an uninstall.php file with a call to delete_transient( 'ozh_livecounter' ); to make sure things are clean when uninstalled, and much more.
Shorter URL
Want to share or tweet this post? Please use this short URL: http://ozh.in/rx
Interesting API indeed. Would have been perfect for the cache of my Simple Flickr Photostream plugin if the set_transient had a callback on deletion.
So when WordPress deletes the transient it also fires a function that would delete a picture file for example.
Will keep it in mind for future plugin development, thanks Ozh.
Hi,
In the example you expire the array after 3 minutes but don't you have to expire each ip at a time? In the current case, if you have a new visitor each two minutes the list will grow for ever.
Am I missing something?
Ben » It's easy, there's actions inside delete_transient() for this: add_action( 'delete_transient_simpleflickrstream', 'sfp_delete_picture' ). Look in the source of the function in wp-includes/functions.php
Elad » ahah yeah totally. I'm dumb :) Will update this :)
Awesome, I did not look in the code, just went on the codex. I'll definitely use that for caching then, it's perfect. Thanks again.
Very good
I wrote about it in my blog
http://www.ma7abah.com/blog/832.html
Ozh,
Thanks for this writeup, I just used the Transient API in one of my plugins after starting to use the wp_cache_* functions ( http://codex.wordpress.org/Function_Reference/WP_Cache ) then noting that they weren't persistent after WP 2.5 unless a pluggable caching mechanism was being used on the site. The Transients API will also be sped up if a caching plugin is in use as well.
This is like Drupal's get_variables and set_variables function, but this one has expiration.
I'm developing a WordPress site now and I believe I can use the Transients API for the project.
Thanks Ozh!
Thanks for this. Now I understand what all these transients were about in my database.
The options table in WP is getting rather bloated now though, isn't it?
I wonder how efficient it is to have to search on option name to get a value many many times when generating a page and running many plugins.
Of course caching can solve this problem for published pages.
It should maybe be a rule that plugins may only have one option and this may be an array.
I understand this is just example but you advice users to use this code. Also I saw such coding patterns in WP core too. And I can say this is total ignoring of concurency issues.
Great example is cron emulation in wp. With high use lost scheduled tasks guaranted.
OZH is the best! :D
tnx a lot for your tutorial!
Is this like the thing in Codeigniter that allows messages to be sent on the nest page reload?
Is there a way to clear it after the next reload? Be very handy for messages.
Great Tutorial man and ther aint a lot of good examples out their using transient
Thank
Sagive