Tweets in WordPress with Backups

Update (20 January 2013): There is a newer version of this script available now: Authenticate Your Twitter API Calls Before March.

Around this time last year, I showed you how to embed tweets in WordPress using the Twitter API.

Today, I want to improve on that script by adding a backup to it. Twitter is often down or unresponsive, and when it is, the previous script fails and displays nothing.

With a backup, we store an extra copy of each set of tweets that we find. When Twitter is down, we can then use this backup to display tweets as normal.

WordPress “Transients” vs “Options”

We will use both of these, so it’s best to explain quickly what they are. An “option” is a value that is stored permanently in your database. There is an option for your site title, the slogan etc.

A transient is very similar to an option, but it also has an expiry time. After this time, the transient is deleted. For more information, read using the Transients API.

The transient is perfect for caching tweets. We can store the results from Twitter, and when the transient expires, fetch new ones.

The option however is perfect for the backup, because we never want it to expire (We will just write over it each time we update it).

The Code

The majority of this code is from the previous article. For that reason, I will only explain the new additions. To understand how we process each tweet and display it, check out the original post.

And if you’d rather just skip on, you can grab the fully completed code here.

Find where in your theme you would like the tweets to appear (e.g. sidebar.php), and paste the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
/*
 * JSON list of tweets using:
 *         http://dev.twitter.com/doc/get/statuses/user_timeline
 * Cached using WP transient API.
 *        http://www.problogdesign.com/wordpress/add-a-backup-to-embedded-tweets-in-wordpress/
 */
 
// Configuration.
$numTweets = 3;
$name = 'problogdesign';
$cacheTime = 5; // Time in minutes between updates.
$exclude_replies = false; // Leave out @replies?
 
$transName = 'list-tweets'; // Name of value in database.
$backupName = $transName . '-backup'; // Name of backup value in database.

These are your configuration options. How many tweets do you want to display? From which user? And how often should we fetch new updates? (It’s fine to go to 1 minute even, but it means one of your users will have a slow page load every minute, rather than one every 5 minutes).

The only change from before is that I’ve added the option to exclude @replies from your results, and we now have 2 names for values in the database. Let’s carry on.

The next section of code is the bulk of the script. Essentially, it fetches the data from Twitter’s API, picks out the parts we want, formats them, and saves them as an array called $tweets. The original post explains it all one step at a time.

You can also read about this specific Twitter API call here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Do we already have saved tweet data? If not, lets get it.
if(false === ($tweets = get_transient($transName) ) ) :    
 
    // Get the tweets from Twitter.
    $response = wp_remote_get("http://api.twitter.com/1/statuses/user_timeline.json?screen_name=$name&count=$numTweets&exclude_replies=$exclude_replies");
 
    // If we didn't find tweets, use the previously stored values.
    if( !is_wp_error($response) && $response['response']['code'] == 200) :
        // Get tweets into an array.
        $tweets_json = json_decode($response['body'], true);
 
        // Now update the array to store just what we need.
        // (Done here instead of PHP doing this for every page load)
        foreach ($tweets_json as $tweet) :
            // Core info.
            $name = $tweet['user']['name'];
            $permalink = 'http://twitter.com/#!/'. $name .'/status/'. $tweet['id_str'];
 
            /* Alternative image sizes method: http://dev.twitter.com/doc/get/users/profile_image/:screen_name */
            $image = $tweet['user']['profile_image_url'];
 
            // Message. Convert links to real links.
            $pattern = '/http:(\S)+/';
            $replace = '<a href="${0}" target="_blank" rel="nofollow">${0}</a>';
            $text = preg_replace($pattern, $replace, $tweet['text']);
 
            // Need to get time in Unix format.
            $time = $tweet['created_at'];
            $time = date_parse($time);
            $uTime = mktime($time['hour'], $time['minute'], $time['second'], $time['month'], $time['day'], $time['year']);
 
            // Now make the new array.
            $tweets[] = array(
                            'text' => $text,
                            'name' => $name,
                            'permalink' => $permalink,
                            'image' => $image,
                            'time' => $uTime
                            );
        endforeach;
 
        // Save our new transient, and update the backup.
        set_transient($transName, $tweets, 60 * $cacheTime);
        update_option($backupName, $tweets);

The change to notice comes on line 8. Here, we check if an error occurred or Twitter failed to give us back our tweets. We check the latter by looking at the HTTP status code returned. You can read more about how Twitter uses status codes here, but the short of it is that anything other than 200 means something went wrong.

We only process the page returned if it passes these two checks.

The other change is on the very last line, where we save the transient as normal, but also save the permanent “option”. This updates our backup with the most recent set of results.

Moving on, all we need to do if the fetch fails is populate the $tweets array with the value from our permanent backup.

1
2
3
    else : // i.e. Fetching new tweets failed.
    	$tweets = get_option($backupName); // False if there has never been data saved.
	endif;

Now we can display the tweets as before. To check that we do have tweets to display, we check if $tweets is false (If a backup has never been made, get_option() will have returned false to it).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Now display the tweets, if we can.
if($tweets) : ?>
    <ul id="tweets">
    <?php foreach($tweets as $t) : ?>
        <li>
            <img src="<?php echo $t['image']; ?>" width="48" height="48" alt="" />                
            <div class="tweet-inner">
                <p>
                     <?php echo $t['name'] . ': '. $t['text']; ?>
                     <span class="tweet-time"><?php echo human_time_diff($t['time'], current_time('timestamp')); ?> ago</span>
                </p>
            </div><!-- /tweet-inner -->
        </li>
    <?php endforeach; ?>
	</ul>
	<p><a href="http://twitter.com/#!/<?php echo $name; ?>">[ Follow us on Twitter ]</a></p>
 
<?php else : ?>
	<p>No tweets found.</p>
<?php endif; ?>

At the end, I’ve added a simple error message, rather than displaying nothing. This will only appear if fetching tweets fails, and a backup has never been made.

And that’s it done. If you used the previous script, this can be slotted in over it and all you need to do is update your details in the configuration section at the top. Now your tweet list should be that bit more reliable.

The full code can be found here.

Enjoy this post? You should follow me on Twitter!