Skip to content
This repository has been archived by the owner on Dec 4, 2018. It is now read-only.
Jaisen Mathai edited this page Jul 3, 2013 · 24 revisions

Table of Contents

  1. Dependencies
  2. Usage and examples
  3. Method based API
  4. Uploading images using multipart
  5. Using the oauth_callback parameter
  6. Efficiently using asynchronous curl
  7. Creating an OAuth application on Twitter
  8. Common errors

Getting started

Twitter-async lets you easily integrate with Twitter’s REST API using either basic authentication or OAuth. In addition to being easy to use, it supports asynchronous calls.

If you would like a walk-through tutorial then you can read the following blog posts.

Dependencies

  1. PHP 5.2 or higher
  2. EpiTwitter, EpiOAuth and EpiCurl (included with the repository)

Usage and examples

Some of the Twitter API endpoints require authentication while others don’t. For authenticated API calls you can provide credentials using either basic authentication or OAuth. Basic authentication requires that you send the username and password of the account you want to use. OAuth let’s you pass tokens, instead of passwords, to make authenticated calls. Twitter-async makes it easy by exposing an extremely simple API.

  • get($endpoint[, $params])GET request using OAuth
  • post($endpoint[, $params])POST request using OAuth
  • delete($endpoint[, $params])DELETE request using OAuth
  • get_basic($endpoint[, $params, $username, $passwords])GET request using none or basic authentication
  • post_basic($endpoint[, $params, $username, $passwords])POST request using none or basic authentication
  • delete_basic($endpoint[, $params, $username, $passwords])DELETE request using none or basic authentication
  • A method based API also exists
  // Calls which do not require authentication
  $twitterObj = new EpiTwitter();
  $trends = $twitterObj->get_basic('/trends.json');
  echo $trends->responseText;

  // Calls requiring authentication
  // Basic authentication
  $twitterObj = new EpiTwitter();
  $creds = $twitterObj->get_basic('/account/verify_credentials.json', null, 'username', 'password');
  echo $creds->responseText;
  // OAuth
  $twitterObj = new EpiTwitter($consumerKey, $consumerSecret, $oauthToken, $oauthSecret);
  $creds = $twitterObj->get('/account/verify_credentials.json');
  echo $creds->responseText;

Accessing the response

All calls to Twitter APIs return an object with properties. The properties are named identical to what is in the response and dimensions of 2 or more are exposed as arrays. For example, the following JSON response is from the verify credentials API.

  {
    screen_name: "jmathai",
    name: "Jaisen Mathai",
    status: {
      text: "My last status",
      created_at: "Thu Apr 09 15:00:07 +0000 2009"
    },
  }

Each of these values can be accessed the following ways.

  // Access properties directly as member variables
  $userInfo->screen_name;
  $userInfo->name;
  $userInfo->status->text;
  $userInfo->status->created_at;

  // Access properties as an array through the response property
  $userInfo->response['screen_name'];
  $userInfo->response['name'];
  $userInfo->response['status']['text'];
  $userInfo->response['status']['created_at'];

Exposing the response headers

You can access the response headers for your request by checking the $resp->headers array.

  $resp = $twitterObj->get_search(array('q' => 'twitter'));
  var_dump($resp->headers);
  echo "You have {$resp->headers['X-RateLimit-Remaining']} calls remaining";

A note on enumerated lists

Some responses are returned as an enumerated list. Since PHP requires that object properties start with [a-Z_] you can’t use $resp->0->screen_name. Given the following JSON response, you can use either of the methods described below.

  [
    {
        screen_name: "jmathai",
        name: "Jaisen Mathai"
        ...
    },
    {
        screen_name: "jmathai",
        name: "Jaisen Mathai"
        ...
    },
    ...
  ]
  // Access the respose as an array
  $firstFollower = $resp[0]->screen_name

  // Loop over the response as an an array
  foreach($resp as $follower){
      echo $follower->screen_name;
  }

Catching and handling exceptions

Twitter-async throws an exception anytime the HTTP response code is not between 200 and 399. For debugging purposes, accessing responseText doesn’t follow this pattern and will always return the raw response. It’s recommended that you catch specific exceptions in favor of the base Exception. Here is an example of catching an EpiTwitterException and falling back to the base Exception.

NOTE: If you have set the library to operate asynchronously the exception isn’t thrown until you access any of the return values from the API call.

  try{
    $twitterInfo = $twitterObj->get_accountVerify_credentials();
    echo $twitterInfo->screen_name;
  }catch(EpiTwitterException $e){
    echo 'We caught an EpiOAuthException';
    echo $e->getMessage();
  }catch(Exception $e){
    echo 'We caught an unexpected Exception';
    echo $e->getMessage();
  }

Exception hierarchy

  • EpiTwitterException extends Exception – General uncaught or unknown exceptions
  • EpiTwitterBadRequestException extends EpiTwitterException – 400 response code
  • EpiTwitterNotAuthorizedException extends EpiTwitterException – 401 response code
  • EpiTwitterForbiddenException extends EpiTwitterException – 403 response code
  • EpiTwitterNotFoundException extends EpiTwitterException – 404 response code
  • EpiTwitterNotAcceptableException extends EpiTwitterException – 406 response code
  • EpiTwitterEnhanceYourCalmException extends EpiTwitterException – 420 response code
  • EpiTwitterInternalServerException extends EpiTwitterException – 500 response code
  • EpiTwitterBadGatewayException extends EpiTwitterException – 502 response code
  • EpiTwitterServiceUnavailableException extends EpiTwitterException – 503 response code

Method based API

The __call method handles the method based API invocations. There’s a simple naming pattern used to determine the proper method you want to call for a given API endpoint. Let’s start with the most common first example of validating a set of credentials.

Documentation on Twitter’s site.

  $twitterObj = new EpiTwitter(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, $userToken, $userSecret);
  $userInfo = $twitterObj->get_accountVerify_credentials();
  // access keys directly
  echo "Your Twitter username is {$userInfo->screen_name}";
  // access response text
  echo $userInfo->responseText;
  // access response as an array
  var_dump($userInfo->result);

Understanding method names

The method based API directly maps to API endpoints. In the example above, the method name get_accountVerify_credentials consists of the HTTP method (get) and the url path (account/verify_credentials). Simply follow these rules to determine the proper method name.

  1. The first part is the HTTP method (in lowercase) specified by the API docs (i.e. get, post) get
  2. Follow the method with an underscore get_
  3. The second half of the method name is the URI path. This is entirely lowercase except for when there needs to be a / which is denoted by a capital letter get_accountVerify_credentials
  4. The method takes an associative array as a list of parameters to be sent along with the request get_accountVerify_credentials(array('name'=>'value'))
  /* GET -> /followers/ids.json?screen_name=yahoo */
  $twtObj->get_followersIds(array('screen_name' => 'yahoo'));

  /* POST -> /statuses/update.json?status=This+is+my+new+status */
  $twtObj->post_statusesUpdate(array('status' => 'This is my new status'));

  /* GET -> /statuses/followers/jmathai_test.json */
  $userId = ucwords(strtolower($userId));
  $method = "get_statusesFollowers{$userId}"; // $userId = jmathai_test
  $twtObj->$method();

Uploading images using multipart

Twitter-async supports uploading images via the Twitter API using OAuth. To specify the image parameter to the account/update_profile*image endpoints you’ll need to prepend the key and value with an @. The path to the file must be the absolute path to the file on the server. This is not yet supported with basic authentication.

  $twitterObj->post('/account/update_profile_image.json', array('@image' => '@/tmp/myfile.jpg'));
// http://github.com/jmathai/twitter-async/issues#issue/68
// some people have issues with the image uploading and a suggested workaround is to add the  mime type
$twitterObj->post('/account/update_profile_image.json', array('@image' => '@/tmp/myfile.jpg;type=image/jpeg'));

Using the oauth_callback parameter

In the 1.0a version of the API Twitter added support for an oauth_callback paramter. This parameter allows you to programmatically specify the callback url which Twitter redirects to. Originally, Twitter would always redirect the user back to the URL you specified in your OAuth settings.

To specify a different callback url you can pass in a parameter into getAuthenticateurl or getAuthorizeUrl.

  $url = $twitterObj->getAuthorizeUrl(null,array('oauth_callback' => 'http://mysite.com/custom/callback'));
  echo '<a href="'.$url.'">Authorize with Twitter</a>';

Twitter associates the URL you specified with the OAuth token they give back to you. This url works like normal and when the user visits it they will be taken to Twitter’s OAuth page as normal. Once they authorize usage of your application then Twitter will forward the user to the URL you specified. They will include an additional parameter in the url named oauth_verifier. This parameter needs to be passed in to getAccessToken in order to exchange the request token for an access token. Aside from these two additional parameters the flow is identical except you can specify the callback URL at run time.

  $twitterObj->setToken($_GET['oauth_token']);  
  $token = $twitterObj->getAccessToken(array('oauth_verifier' => $_GET['oauth_verifier']));
  $twitterObj->setToken($token->oauth_token, $token->oauth_token_secret);
  $twitterInfo = $twitterObj->get_accountVerify_credentials();
  echo $twitterInfo->screen_name;

Efficiently using asynchronous curl

Twitter-async was carefully written to maximize the efficiency of making HTTP web service requests. Knowing that curl calls are expensive, we don’t want to wait around idly while we could be doing other work. This is especially true if you need to make multiple calls on a single page. Ideally, you could fire off several requests in parallel instead of doing them one at a time. To enable asynchronous calls you will need to call useAsynchronous(true) on the Twitter-async object.

The key to using Twitter-async efficiently is to delay accessing the results for as long as possible. Initiating the call fires off the HTTP request and immediately returns control back to you without blocking. The call continues to work in the background until you need the results. For the best performance it’s advised to initiate the calls as early as possible and only block by accessing the results as late as possible. The implementation details depend greatly on your framework.

  $twitterObj = new EpiTwitter(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, $userToken, $userSecret);
  $twitterObj->useAsynchronous(true);
  $followers = array('user1','user2','user3','user4','user5');
  $responses = array();
  // send off the requests in parallel
  foreach($followers as $follower) {
    $responses[] = $twitterObj->post_direct_messagesNew( array('user' => $follower, 'text' => "Hey {$follower} what's up?"));
  }

  // now we retrieve the results and ensure that each call completes
  foreach($responses as $response) {
    echo "Direct message had an id of {$response->id}\n";
  }

Using the sequencer to verify asynchronous requests

It’s important to validate that your calls are truly asynchronous. The library includes a sequencer class which displays a graph of the calls to show you how the calls are sequenced. You can look at the file tests/sequencerTest.php for an example.

// To display the sequence graph you can add the following code to the bottom of your page.
echo EpiCurl::getSequence()->renderAscii();

// To run the example you can execute the sequencerTest.php file from the command line
`php sequencerTest.php`
Test sequencing diagram of api calls

(http://api.twitter.com/1/direct_messages.json ::  code=200, start=1283577305.2462, end=1283577305.5109, total=0.264562)
[====================================================================================================]
(http://api.twitter.com/1/users/suggestions.json ::  code=200, start=1283577305.2726, end=1283577305.3871, total=0.114419)
[         =============================================                                              ]
(http://api.twitter.com/1/statuses/public_timeline.json ::  code=200, start=1283577305.2731, end=1283577305.4195, total=0.146262)
[          ========================================================                                  ]

Creating an OAuth application on Twitter

To start off, you’ll need to create an application on Twitter. They will give you a consumer key and a consumer secret. Copy and paste this into your site’s configuration file since you’ll be needing them later. The rest of the information is embedded in Twitter-async.

  define('TWITTER_CONSUMER_KEY', 'your_consumer_key');
  define('TWITTER_CONSUMER_SECRET', 'your_consumer_secret');

Common OAuth errors

  1. Failed to validate oauth signature and token
    • Make sure your system clock is correct (source)
  2. Curl error – name lookup timed out.
    • Increase time out of request and connection, using setTimeout() method on the client.
  3. Non ascii characters throw errors.
    • Convert the string first using iconv("ISO-8859-1", "UTF-8", 'Your string here'). Related bug