
This write-up will go through the process of displaying your Twitter tweets on a web page using a little bit of PHP. Learn how to read your Twitter RSS Feed, Cache it and then display it.
Sure, you can probably use a widget, but, maybe you want to do something custom or maybe build your own widget.
Getting Your Twitter RSS Feed
First you will want to find your Twitter RSS feed link, copy the link location as you will use this in the code below. My RSS link looks like this:
http://twitter.com/statuses/user_timeline/18060713.rss
The Solution
Here is the code, I’ll explain the different parts below: [+ show code]
Taking it Step By Step
When using the code above, there are four key variables which you can adjust: $url is your twitter feed url, $cache_expire is the amount of time (in seconds) that the twitter feed will be remembered, $info_file and $cache_file are the data files used by the script to remmeber the Twitter feed, you probably will not need to change the location of these files.
$url = 'http://twitter.com/statuses/user_timeline/18060713.rss'; $cache_expire = 3600; // in seconds $ts = time(); $info_file = 'tmp-info.txt'; $cache_file = 'tmp-'.$ts.'.xml';
Lets go through how the script does its thing: first it trys to open the “info” file and get some information about the “cache” file.
// current info $info = unserialize(@file_get_contents($info_file));
Then the script checks if the cache files have expired. The if statement basically reads like this: “if there is no info or the current time is greater than when the cache was set to expire” …
if (empty($info) OR $ts > ($info['cache_ts']+$cache_expire))
Lets first explore if the statement is FALSE: this means that the cache has not expired yet. This is the simplest scenario, the script simply reads the cache file and gets the content.
$content = file_get_contents($info['cache_file']);
However, if the statement is TRUE, the script will get your latest tweets from Twitter (it uses CURL to request the feed as most servers have it enabled).
$ch = curl_init(); curl_setopt ($ch, CURLOPT_URL, $url); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); $content = curl_exec($ch); curl_close($ch);
The script confirms the content with a simple check, basically looking for the presence of a specific XML element. If it finds it, it assumes that all is OK and writes the contents to a file. Additionally, the old cache file is removed.
// if a description tag is present we're OK
if (preg_match('/<description>/iS',$content))
{
file_put_contents($cache_file,$content);
@unlink($info['cache_file']);
}
If the check fails, the script assumes that some sort of error has occured. Instead of writing any new data, the script gets the old data and resets the “info” file to be checked again at a new expire time (giving any errors time to resolve itself).
// known error strings: "over capacity", "rate limit exceeded"
// else if a description tag is not present something is wrong
else
{
// use current cache until errors resolve itself
$cache_file = $info['cache_file'];
$content = file_get_contents($info['cache_file']);
}
// update next cache time and cache file name
file_put_contents($info_file,serialize(array('cache_ts'=>$ts,'cache_file'=>$cache_file)));
Once the script has the RSS content it needs and all the cache files have been updated, it then loops the XML content and creates an array to be used somewhere on the page.
$feed = array();
$doc = new DOMDocument();
$doc->loadXML($content);
foreach ($doc->getElementsByTagName('item') as $node)
{
array_push($feed, array
(
'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
'desc' => preg_replace('/^\w+:/i','',$node->getElementsByTagName('description')->item(0)->nodeValue),
'link' => $node->getElementsByTagName('link')->item(0)->nodeValue,
'date' => $node->getElementsByTagName('pubDate')->item(0)->nodeValue
));
}
Outputting The Twitter Feed
With the array that was created, looping the feed content is straight forward, here is an example of outputting the feed to the page (in this example we output only the most recent 5 tweets):
<?php if (is_array($feed)): ?> <ul> <?php array_splice($feed,5); ?> <?php foreach ($feed as $item): ?> <li><?php echo linkify_tweet($item['desc']); ?></li> <?php endforeach; ?> </ul> <?php endif; ?>
You may have also noticed that the linkify_tweet function being used in this example, it basically makes URLs, usernames and hashtags into clickable links.
function linkify_tweet($v)
{
$v = ' ' . $v;
$v = preg_replace('/(^|\s)@(\w+)/', '\1@<a href="http://www.twitter.com/\2">\2</a>', $v);
$v = preg_replace('/(^|\s)#(\w+)/', '\1#<a href="http://search.twitter.com/search?q=%23\2">\2</a>', $v);
$v = preg_replace("#(^|[\n ])([\w]+?://[\w]+[^ \"\n\r\t<]*)#ise", "'\\1<a href=\"\\2\" >\\2</a>'", $v);
$v = preg_replace("#(^|[\n ])((www|ftp)\.[^ \"\t\n\r<]*)#ise", "'\\1<a href=\"http://\\2\" >\\2</a>'", $v);
$v = preg_replace("#(^|[\n ])([a-z0-9&\-_\.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i", "\\1<a href=\"mailto:\\2@\\3\">\\2@\\3</a>", $v);
return trim($v);
}

Awesome work.. this is exactly what I needed. Also here’s some additional code for anyone wanting to output a bit more:
<?php foreach ($feed as $item): ?> <h2><a href="<?=$item['link']?>"><?=date('F j, Y - g:ia', strtotime($item['date']))?></a></h2> <p><?=linkify_tweet($item['desc'])?></p> <?php endforeach; ?>Basically I cleaned up the date output with the strtotime() function. To format the date to your liking you should refer to PHP date() formats
Great script man… would be great to expand this a bit more for less savvy php users.
Is it just me or is the Title and Desc in the RSS the same data?
Hi!
Any way to include replies?
Thanks!
Twitter does have a RSS feed for replies, however it is behind basic auth (I know twitter will be moving to OAuth at the end of June/2010 (not sure if it also applies to this).
As an example I would be able to access my replies feed at the following URL (not all browsers support this type of URL, but you’ll be making a PHP CURL request, so it shouldn’t be a problem):
Thanks.
FYI I’ve just made it building a Yahoo pipe from scratch, see the result in my homepage (lower right corner, LAST TWEETS), and tell me what do you think.
@flapane, very nice! Great idea with the Yahoo pipes. I assume you are merging both feeds into one…
Thanks !!
I’m use this with “jQuery .load()”
Idea …
Markus, that is a very good idea. The overall page load would be much quicker also.
Just what I was looking for! Worked a treat!
Also altered it slightly to bring in our Tumblr blog from the RSS feed.
This is awesome, been browsing for days trying to find something that actually works.
Just one question based on Jesse’s comment, any idea how to output the time as “time ago” rather than just output the exact date from the rss file?
Hi Peter, here are two options for you:
1)
human time diff()… a wordpress function2) this is a function I recently used for a foursquare widget I wrote.
You will probably want to convert the time to a timestamp first, using
strtotime(), with something like:'date' => strtotime($node->getElementsByTagName('pubDate')->item(0)->nodeValue)Thanks for the reply Dimas,
Seems that it keeps outputing 705 days for all tweets :S not sure where i’ve gone wrong.
I’m not really that experienced in PHP, seems pretty straight forward though when using human_time_diff on comments or posts from within WP but i can’t seem to figure out how to implement it into your twitter code.
Any help?
It’s actually outputing the following: “14839 days ago” for each tweet.
I modified the date in the array as you suggested above and then used the following to print the time:
echo human_time_diff(('date'), current_time('timestamp')) . ' ago';Peter, assuming you added the strtotime bit to the main code … you should be able to do the following:
That did the trick! Thanks again Dimas.
Nice, worked well used it to pull other rss feeds too thanks.
thanks for the code, exactly what I needed!
Thanks for this post Dimas, I just set it up myself and it works beautifully!
This code is just what I was looking for. But it seems like Twitter doesn’t allow RSS-Feeds anymore. Do you know an alternative way?
@Bastian, RSS feeds still work fine, see the following format:
I get the following errors –
Warning: file_put_contents(tmp-1315951485.xml): failed to open stream: Permission denied in C:\web\includes\twitter.php on line 26 Warning: file_put_contents(tmp-info.txt): failed to open stream: Permission denied in C:\web\includes\twitter.php on line 42
However, the tweets come out ok. I’m assuming that means it can’t create a cache file. I’m on win 2008 IIS7. I’ve used php cgi-wrap for linux in the past to get around permissions issues….Not sure what to do with Windows…. Thanks for the great tutorial!
Is there a way of using php to integrate a specific list I’ve got set up on my twitter account so that users on my website will only view tweets from accounts in a specific list?
Hi,
I’ve modified it slightly but it is working great. How would you go about cleaning up old cache files? I think you really only need to store the one cache file, right?
Hoping you have a solution. If you delete the cache files, it will spit an error msg. You then refresh and the tweets show up. The cache files also do exist at that point.
So i think there’s a bug in the script where the first time it runs, it has to create the files, but creates them after it loads. So because of this it errors out.
Any solution for this??
@Pendo, yes it is a file read/write permission thing (sorry for the really late response)
@Edd, you could retrieve just specific feeds as need, additionally you could use something like yahoo pipes to merge two or more twitter feeds into one, and use the above code to read in the merged feed.
@Brent, the solution above will only use two cache files and and will clean up after itself as it writes a new cache file.
@crashfellow, what errors are you getting?
Has the solution changed since my comment? If not, it hasn’t been cleaning up for me. Perhaps I implemented it incorrectly …