Today I will be showing you how to use cURL to get your Twitter status and cache it into a file on your server. This file will then be read with JavaScript and displayed on the web-page. Before we start you can view a demo and download the final files below:
The widget will have the following file structure

Twitter has an API limit (currently 150 calls per hour) so its best to use your username/password to make sure that you will get a successful response. If you don’t (as far as I know) Twitter will use the API calls that are for everyone with your IP/Servers IP. This means that if other people on your server are also using data from twitter (that requires an API call), it will start to give an error saying that you have used up your API limit very quickly.
<?php
function twitterCapture() {
// Set your username and password here
$user = 'twitter_username'; // Twitter Username
$password = 'xxxxxxxx'; // Twitter Password
$tw = curl_init("http://twitter.com/statuses/user_timeline/{$user}.json"); //grabs the JSON format of your timelines
curl_setopt($tw,CURLOPT_TIMEOUT, 30); // Timeout (for when Twitter is down)
curl_setopt($tw,CURLOPT_USERPWD,$user . ":" . $password); // Uses your username and password
curl_setopt($tw,CURLOPT_RETURNTRANSFER,1); // returns
$json = curl_exec ($tw); // Executes the cURL and puts it into the varible
return $json; // returns what was grabbed
}
$cachefile = 'cache/twitterCache.json'; // the location to your cache file
$cachetime = 10 * 60; // set the cach time 10 * 60 (1 hour)
// if the file exists // if and the time it was created is less then cache time
if ( (file_exists($cachefile)) && ( time() - $cachetime < filemtime($cachefile) ) ) {
// script will not use the cached version
}else{ // the file didn't exist or is old
ob_start(); // turn on the output buffering
$fp = fopen($cachefile, 'w'); // opens for writing only or will creat it's not there
fwrite($fp, twitterCapture()); // writes to the file what was grabbed from the previouse function
fclose($fp); // closes
ob_end_flush(); // finishes and flushes the output buffer
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Little Twitter Widget</title>
<!-- Start of CSS -->
<link rel="stylesheet" type="text/css" href="css/reset.css" />
<link rel="stylesheet" type="text/css" href="css/main.css" />
<!-- Start of JS -->
<script type="text/javascript" src="js/jquery-1.4.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</head>
<body>
<div id="twitter_widget_top" class="center" ></div><!-- The top of the widget -->
<div id="twitter_widget_body" class="center"> <!-- The body wrap -->
<div id="twitter_widget_tweet"> <!-- The tweet area -->
<div id="twitter_movement"> <!-- To position the icon reletive to -->
<a id="twitter_icon" href="http://twitter.com/"></a> <!-- Twitter icon -->
<div id="twitterWrap"> <!-- The blue area -->
<div id="twitter"> <!-- The main twitter data -->
<noscript>JavaScript must be on to view tweets</noscript> <!-- Incase no js -->
<p class="tweet">Loading...</p> <!-- The Tweet -->
<p class="created_at"></p> <!-- Date created -->
</div>
</div>
<p class="clear"></p> <!-- Clear the floats -->
</div>
<a href="" class="previous tweetNav"></a><!-- Next button -->
<p class="follow_me">Follow me - <a href="http://twitter.com/alexanderbor" class="screen_name"></a></p> <!-- Follow me link -->
<a href="" class="next tweetNav"></a> <!-- Pre button -->
<p class="clear"></p>
</div>
</div>
<div id="twitter_widget_bottom" class="center"></div><!-- Bottom of widet -->
<p class="info">Join my <span class="followedNumber"></span> followers - <span class="user_name"></span></p>
</body>
</html>
This will check if the cache file exists and then how old it is. If its older than how long we want to leave before getting a new copy then will run the function to grab the new copy of the your twitter stream in JSON format. This is then written to your server in the cache file.
@charset "UTF-8";
/* CSS Document */
/* UTULITIES */
.clear{clear: both;}
.push{height: 30px;}
/* END */
/* ORDER PAGE CORRECTLY */
*{margin: 0; padding: 0;}
html{ position: relative;}
body{font-family: Helvetica, Verdana, Arial, sans-serif; width: 100%; height: 100%; background: #1E202A;color:#3494E5;}
.center{margin: 0 auto;}
a{text-decoration:none;color:#4AA1EF; overflow: hidden}
a:hover{color: #3D658E;}
/* END */
#twitter_widget_top{background: url(../images/top.jpg) top left no-repeat; width: 475px; height: 30px;margin-top:81px; } /* Top of widget */
#twitter_widget_body{background: url(../images/body.jpg) left repeat-y; width: 475px;} /*Â BODYÂ */
#twitter_widget_bottom{background: url(../images/bottom.jpg) bottom left no-repeat; width: 475px; height: 21px; } /* foot */
#twitter_icon{background:url("../images/twitter_icon.jpg") no-repeat scroll center bottom transparent;height:50px;margin-left:30px;position:absolute;top:33%;width:50px;}
#twitter_icon:hover{ background-position: top center;} /* Move icon on hover */
#twitterWrap{   /* Don't show overflow and set a width */
overflow: hidden;
width: 350px;
float: right;
background: #1E202A;
margin: 20px 20px 0;
border: 1px solid #062333;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
#twitter_movement{position: relative;} /* To align icon to */
.tweet { /* The Tweet */
font-family:"Lucida Grande",Verdana,Arial,sans-serif;
font-size:15px;
line-height:18px;
padding:15px;
position:relative;
text-align:center;
}
.next{background:url("../images/arrows.jpg") no-repeat right top transparent;float:right;height:14px;margin-right:20px;margin-top:10px;width:21px;}
.next:hover{background-position: right center;} /* Next button */
.previous{background:url("../images/arrows.jpg") no-repeat left bottom transparent;float:left;height:14px;margin-left: 103px;margin-top:10px;width:21px;}
.previous:hover{background-position: left center;}
.created_at {display:block;font-size:12px;font-style:italic;padding-right:20px;text-align:right;}
.follow_me{display:block;float:left;margin:10px;text-align:center;width:280px;}
.info{padding-top:5px;text-align:center;}
To get the twitter status we will use the javascript library jQuery, as this makes it a lot easier. We will use the $.getJSON to grab our cached file.
$(function() {
$.getJSON('cache/twitterCache.json', function(data) { // get the file and put in var "data"
// Add information about the user
$('.followedNumber').html( data[0].user.followers_count); // follow count
$('.screen_name').html( data[0].user.screen_name); // screen name
$('.statuses_count').html(data[0].user.statuses_count); // amount of tweets
$('.user_name').html(data[0].user.name); // username
// defult variables
var totalAmount = "", // total amount of items
moveOut = "", // If we are moving in or out the animation
moveIn = "", // If we are moving in or out the animation
current = 0, // Set the current to 0
$i = 0; // Set i to 0
$.each(data, function(){ // for each of the "data"
totalAmount = $i; // set the varible total amount to i
$i++; // plus one to i
});
clicked(current); // run the function to grab the first item
$(".next").click(function(){ // when next is clicked
if ($(this).hasClass('active') ){ // if it's active
current = current + 1; // set current to + 1
moveOut = "+"; // make the move out animation correct
moveIn = "-"; // same with move in
clicked(current); // run the function and pass in current
}; // no else, so nothing will happen if we click when not active
});
$(".previous").click(function(){ // almost the same as above
if ($(this).hasClass('active') ){
current = current - 1; // minus one from the tcurrent
moveOut = "-";
moveIn = "+";
clicked(current);
};
});
//
// Time function from the Twitter Blog JS file
//
function relative_time(time_value) {
var values = time_value.split(" ");
time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
var parsed_date = Date.parse(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
delta = delta + (relative_to.getTimezoneOffset() * 60);
if (delta < 60) {
return 'less than a minute ago';
} else if(delta < 120) {
return 'about a minute ago';
} else if(delta < (60*60)) {
return (parseInt(delta / 60)).toString() + ' minutes ago';
} else if(delta < (120*60)) {
return 'about an hour ago';
} else if(delta < (24*60*60)) {
return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
} else if(delta < (48*60*60)) {
return '1 day ago';
} else {
return (parseInt(delta / 86400)).toString() + ' days ago';
}
}
function clicked(current){ // when clicked function runs
// get the width to be able to slide the tweet area
var tweetAreaWidth = $('#twitterWrap').width();
// fade out the time it was created
$('.created_at').animate({"opacity": "0"}, 400); // fade out the date
$('.tweet').animate({"right": moveOut + tweetAreaWidth + "px"}, function(){ // move the .tweet div left/right then
$('.tweet') .html( data[ current ].text ); // add the next tweet
var time = relative_time( data[ current ].created_at ); // get the next date
$('.created_at').html(time); // put data into useable format
var tweetAreaHeight = $('#twitter').height(); // get the height of the tweet area now its got the tweet inside
$('#twitterWrap').animate({"height": tweetAreaHeight + "px"}, function(){ // change the tweet height to the new div
$('.tweet').css({"right": moveIn + tweetAreaWidth + "px"}).animate({"right": 0}); // move in the tweet
$('.created_at').animate({"opacity": "1"}, 500); // fade in the date
});
});
// dealing with the click buttons
$('.tweetNav').removeClass('inactive').addClass('active'); // remove inactive from all buttons and add active
if(current == totalAmount){ // if current is equal to the total amount make the next button inactive
$('.next').removeClass('active').addClass('inactive');
}
if(current == 0){
$('.previous').removeClass('active').addClass('inactive');
}
$('.inactive').animate({"opacity": "0.3"}, 1000); // make inactive buttons fade out
$('.active').animate({"opacity": "1"}, 500); // made active buttons fade in
$('.tweetNav').click( function(){ return false; }); // return false
}; // end of clicked function
});// end of json
});
This should now work, a great way to see how to access the elements that are returned is using FireBug as this lets us see the name of the json elements and what is nested in them.

I hope that you have found this interesting and now have a working animated twitter widget.
Gemstone rings are the most coveted accessory items to date. Also, LusterForever earrings are a must to try on.
What an amazing lesson ! Thank you so much
[...] Build a PHP Twitter Widget | Brenelz Web Design Solutions [...]
[...] Build a PHP Twitter Widget By Alex, March 23rd, 2010 Site: Brenelz [...]
Awesome ! thank you
[...] tutorial will teach us how to use cURL to get your Twitter status and cache it into a file on your server. [...]
[...] Čítať ďalej originálny článok Komentáre (0) k článku “Build a PHP Twitter [...]
[...] tutorial will teach us how to use cURL to get your Twitter status and cache it into a file on your server. [...]
Can you explain how to do this in Flash AS3?
December 21st, 2010 at 9:04 pm
This is a great tutorial! Everything works and looks great.
My sister told me about this site just yesterday. Great blog you’ve got!
A very interesting article and the code is lovely. I will try to work out
the widget ASAP.
Twitter
Follow me on Twitter to keep up to date!
RSS Feed
Keep up with all of our updates by subscribing to our RSS feed!
FaceBook
Join our group on Facebook and become a fan of us!