=^.^=

Parsing and Embedding Twitter Feeds in PHP

Twitter feeds can be obtained in XML with this URL scheme:

http://twitter.com/statuses/user_timeline/$username.xml?count=$count

Where $username is the twitter user's name and $count is how far back you want to go.

If your environment allows url_fopen you can load the whole thing directly into an object with simplexml_load_file().

Portability is good and allow_url_fopen is arguably very dangerous. For the sake of brevity let's rip this class from the PHP manual's fopen() comments:

class HTTPRequest
{
    var $_fp;        // HTTP socket
    var $_url;        // full URL
    var $_host;        // HTTP host
    var $_protocol;    // protocol (HTTP/HTTPS)
    var $_uri;        // request URI
    var $_port;        // port
   
    // scan url
    function _scan_url()
    {
        $req = $this->_url;
       
        $pos = strpos($req, '://');
        $this->_protocol = strtolower(substr($req, 0, $pos));
       
        $req = substr($req, $pos+3);
        $pos = strpos($req, '/');
        if($pos === false)
            $pos = strlen($req);
        $host = substr($req, 0, $pos);
       
        if(strpos($host, ':') !== false)
        {
            list($this->_host, $this->_port) = explode(':', $host);
        }
        else
        {
            $this->_host = $host;
            $this->_port = ($this->_protocol == 'https') ? 443 : 80;
        }
       
        $this->_uri = substr($req, $pos);
        if($this->_uri == '')
            $this->_uri = '/';
    }
   
    // constructor
    function HTTPRequest($url)
    {
        $this->_url = $url;
        $this->_scan_url();
    }
   
    // download URL to string
    function DownloadToString()
    {
        $crlf = "\r\n";
       
        // generate request
        $req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf
            .    'Host: ' . $this->_host . $crlf
            .    $crlf;
       
        // fetch
        $this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '') . $this->_host, $this->_port);
        fwrite($this->_fp, $req);
        while(is_resource($this->_fp) && $this->_fp && !feof($this->_fp))
            $response .= fread($this->_fp, 1024);
        fclose($this->_fp);
       
        // split header and body
        $pos = strpos($response, $crlf . $crlf);
        if($pos === false)
            return($response);
        $header = substr($response, 0, $pos);
        $body = substr($response, $pos + 2 * strlen($crlf));
       
        // parse headers
        $headers = array();
        $lines = explode($crlf, $header);
        foreach($lines as $line)
            if(($pos = strpos($line, ':')) !== false)
                $headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));
       
        // redirection?
        if(isset($headers['location']))
        {
            $http = new HTTPRequest($headers['location']);
            return($http->DownloadToString($http));
        }
        else
        {
            return($body);
        }
    }
}

We also need to give the links anchors, so we'll modify Jonathan Sampson's clever little function to not shorten URLs since twitter already does this for us these days:

function auto_link_text($text)
{
   $pattern  = '#\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))#';
   $callback = create_function('$matches', '
       $url       = array_shift($matches);
       $url_parts = parse_url($url);

       $text = parse_url($url, PHP_URL_HOST) . parse_url($url, PHP_URL_PATH);
       $text = preg_replace("/^www./", "", $text);

       $last = -(strlen(strrchr($text, "/"))) + 1;

       return sprintf(\'<a rel="nowfollow" href="%s">%s</a>\', $url, $text);
   ');

   return preg_replace_callback($pattern, $callback, $text);
}

Here we go:

$username = "username";
$count = 5;
$feed = "http://twitter.com/statuses/user_timeline/$username.xml?count=$count";

$r = new HTTPRequest($feed);
$tweets = $r->DownloadToString();
$twitter_xml = simplexml_load_string($tweets);

$tweet_data = '';
foreach($twitter_xml->status as $status_object)
{
	$tweet_epoch = strtotime($status_object->created_at);
	$tweet_data .= "<div class=\"tweet\"><span class=\"tweet_date\">".date("F j g:ia", $tweet_epoch)."</span><div class=\"tweet_message\">".auto_link_text($status_object->text)."</div></div>";
}

print($tweet_data);

Comments

Graham Morecroft

Thanks for that code snippet. It is working perfectly on my site.