skip to main | skip to sidebar

Twitter API Proxy in PHP
Thanks to the new Twitter API v1.1, it is now impossible to query the API using pure JavaScript code! So, in this quick tutorial will see how to use PHP to do Application-only authentication and forward the API result of the required resource to JavaScript, plus caching API results to prevent rate-limit errors.

Twitter Application Setup

First you need to setup a new Twitter application by filling in that small form.
* By default, new application will be created in "read only" access mode and that is good for Application-only auth. You can check it at : Settings tab > Application type > "Access".

Application-only authentication

To authenticate your API call using Application-only authentication you need to :
1- Base64 Encode your application's "Consumer key" and "Consumer secret", which can be found at your Twitter application page.
2- Submit string from previous step to API and obtain a bearer token.
3- Use bearer token to authenticate your API calls.

Now, lets talk PHP code..

Define these global variables which we will use in next steps:

// fill in your application consumer key & consumer secret & your Twitter username
$consumer_key= '???';
$consumer_secret = '???';
$screen_name = '???';

Define a common function "requestString"

It uses curl to do HTTP POST/GET request and will use it for all API calls.

function requestString( $op ){
   $headers = array();

   // custom headers?   
   if( is_array($op['headers'])){
      foreach ( $op['headers'] as &$value) $headers[ count($headers) ] = $value;
   };

   $ch = curl_init();

   // post?
   if( !empty($op['post']) ){
      $headers[ count($headers) ] = 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8';
      $headers[ count($headers) ] = 'Content-Length: '.(strlen( $op['post'] ));
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $op['post']); // post vars
   };

   curl_setopt($ch, CURLOPT_URL, $op['url']); // request URL
   curl_setopt($ch, CURLOPT_HTTPHEADER, $op['headers']); // custom headers
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   curl_setopt($ch, CURLOPT_HEADER, 0);
   curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); // accept gzip to speedup request

   // if you are testing this script locally on windows server, you might need to set CURLOPT_SSL_VERIFYPEER to 'false' to skip errors with SSL verification
   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true ); // verifying the peer's certificate

   $result = curl_exec ($ch); // execute
   curl_close($ch);

   return $result;
}

Get Bearer Token

Now call the Twitter API to obtain a bearer token as described in steps 1 & 2

function get_bearer_token(){
   global $bearer_token, $consumer_key, $consumer_secret;

   $token_cred = urlencode($consumer_key).':'.urlencode($consumer_secret);
   $base64_token_cred = base64_encode($token_cred);

   $result = requestString( array(
                  'url' => 'https://api.twitter.com/oauth2/token'
                  ,'post' => 'grant_type=client_credentials'
                  ,'headers' => array('Authorization: Basic '. $base64_token_cred)
                  ) );
   $json = json_decode($result);

   $bearer_token = $json->{'access_token'};
}

Authenticate your API Call:

This API call will connect to Users/Show resource which returns variety of information about the required user.
Authentication token (bearer token) is sent to API in custom header "Authorization".

function users_show(){
   global $bearer_token, $screen_name;

   return requestString( array(
                  'url' => 'https://api.twitter.com/1.1/users/show.json?screen_name='. urlencode($screen_name)
                  ,'headers' => array( 'Authorization: Bearer '.$bearer_token )
                  ) );
}

Caching?

Every API method comes with certain rate limits, if you exceed it your script will not work and it will look bad. Therefore, we need to cache the API response for a while. Caching will also speed-up load time noticeably.

To do caching will need to buffer PHP output and write to a file. And at the beginning of this PHP page will check if the cached file date is less than 10 minutes then just include the file, otherwise will proceed with PHP output and write new cache file.

cache_start() is called before returning API result to check for cache file time or start the output buffer:

When content is served from cache, a custom header "x-cached" will show the file date. You can see this header in Firefox(Firebug) or Chrome Inspect.

function cache_start() {
   global $cache_file, $cache_time;

   // Serve from the cache if it is less than $cache_time
   if( file_exists($cache_file) && ( time() - $cache_time < filemtime($cache_file) ) ) {
      // custom header for testing purpose
      header('x-cached: '.date('Y-m-d H:i:s', filemtime($cache_file)));
 
      include($cache_file);
 
      callback_end();
 
      exit;
   }

   ob_start(); // start the output buffer
}

cache_end() is called after returning API result to write the output to file.

function cache_end(){
   global $cache_file;

   // open the cache file for writing
   $fp = fopen($cache_file, 'w');
   // save the contents of output buffer to the file
   fwrite($fp, ob_get_contents());
   // close the file
   fclose($fp);
   // Send the output to the browser
   ob_end_flush();
}

More API Calls ?

Do you usually need another API resource result from this API proxy? why don't you combine the results from different API calls in one array and forward it to your JavaScript..
In this sample I will call statuses/user_timeline to get user Tweets and combine with previous API call in one array.

print '[';
print users_show(); // get user data
print ',';
print user_timeline(); // Get user timeline
print ']';

JSON or JSONP?

If you intend to request this PHP page from client-side code on different domain, then you need to convert the returned JSON to JSONP. JSONP is just about wrapping the JSON object with a function name that will get called once it is loaded.

If the PHP page was requested with a query string parameter "callback" then we need to return JSONP. Will call callback_start() before output and callback_end() after it.

function callback_start(){
   // JSONP callback parameter ?
   $callback = isset($_GET['callback']) ? $_GET['callback'] : '';

   // Content-type for JSON or JSONP
   if( empty( $callback ) ){
      header('Content-Type: application/json; charset=utf-8');
   }else{
      header('Content-Type: application/javascript; charset=utf-8');
      // callback and start Parentheses
      print $callback.'(';
   };
}

function callback_end(){
   // JSONP callback parameter ?
   $callback = isset($_GET['callback']) ? $_GET['callback'] : '';

   // callback and start Parentheses
   if( !empty( $callback ) ) print ')';
}


* for JSON the output content-type is "application/json" while for JSONP it is "application/javascript".

Finally, Consume JSON results in JavaScript

After uploading PHP to your hosting -and paying for it :), it is time to consume the JSON result in JavaScript using jQuery.ajax.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
   $.ajax({
      url:'sample.php'
      ,type: "GET"
      ,dataType: "json"
      ,data: {}
      ,success: function(json){
         var user_show = json[0];
         var user_timeline = json[1];
    
         // display user icon and link to his profile from user_show json
         var html = '<a href="https://twitter.com/'+ user_show.screen_name +'"><img src="'+ user_show.profile_image_url + '"/> '+ user_show.name+'</a>';
    
         // display tweets from user_timeline json
         for(var i=0; i<user_timeline.length; i++){
            var status = user_timeline[i];
            html += '<p>'+ status.text +' <br/><i>'+ status.created_at +'</i><p>';
         };
    
         $('#user_timeline').html( html );
      }
      ,error: function( jqXHR, textStatus, errorThrown ){
         alert(textStatus +' , '+ errorThrown);
      }
   });
})

</script>

<div id="user_timeline"></div>




0 comments

Post a Comment

Thank you for taking the time to comment..
* If you have a tech issue with one of my plugins, you may email me on mike[at]moretechtips.net
More Tech Tips! | Technology tips on web development

Mike

Mike MoreWeb developer, jQuery plugin author, social media fan and Technology Blogger.
My favorite topics are: jQuery , Javascript , ASP.Net , Twitter , Google..
<connect with="me"> </connect>

Subscribe by email

Enter your email address:

or via RSS