Using the Twitter API with PHP and PEAR

April 14, 2009

Tutorials

Using the Twitter API with PHP and PEAR

Tweet Tweet!

Unless you’ve been living in a cave for the last few years, you know what Twitter is – a free online service that allows users to send out concise, real-time updates on what they’re doing at any given moment. These status updates, or “tweets”, can be sent and received through SMS, via the Twitter Web site, or through a variety of third-party applications, and users can subscribe to, or “follow”, each other’s status feeds. Twitter also supports private messaging and search, and has rapidly been growing in popularity as a tool for social networking and near real-time communication.

The really good stuff, though, is hidden behind the scenes. Like many Web 2.0 applications, Twitter exposes its innards to the public via a REST API, making it possible to develop customized applications that run on top of the base service. A number of third-party libraries, written in a variety of different programming languages (including PHP), exist to help developers integrate their applications with this API. This article focuses on one such library, the PEAR Services_Twitter library, which provides a full-featured API for interacting with the Twitter service through a PHP application.

Starting Up

Services_Twitter works by providing a full-fledged, object-oriented interface to the Twitter API. This interface insulates you from the nitty-gritty of working directly with REST requests and, by representing responses as SimpleXML objects, makes it very easy to access specific elements of the returned data. This not only saves time; it’s also simpler, because it’s no longer necessary to be intimately aware of the nitty-gritties of the Twitter API in order to use it effectively.

Before we get started, it’s important to state the assumptions this tutorial makes:

  • First, it assumes that you understand HTML, know the basics of PHP programming with objects and SimpleXML, and are familiar with REST concepts. It also assumes that you have an Apache/PHP/MySQL development environment already set up.
  • Second, it assumes that your PHP installation includes support for the cURL extension. On UNIX systems, this support needs to be enabled at compile-time, by adding the --with-curl option to the configuration script. On Windows, the cURL extension is already included, and simply needs to be activated in the php.ini configuration file. More information on installing this extension can be found here.
  • Third, it assumes that you’ve managed to successfully install the Services_Twitter package. For your reference, this package is freely available from the PEAR Web site, and is currently maintained by Joe Stump and David Jean Louis. This article uses v0.2.0 (beta) of Services_Twitter. To install this package using the PEAR installer, use the following command:


    shell> pear install Services_Twitter-0.2.0
  • Fourth, it assumes that you have a Twitter account. In case you don’t, you can get one by signing up on the Twitter Web site.

With all the pieces installed, let’s play!

Status Check

Let’s begin with a simple example that demonstrates how Services_Twitter works. The following example logs in to your Twitter account and updates your status message with a new value. Here’s the code:

<?php
// include class
include_once 'Services/Twitter.php';

try {
  // initialize service object
  // perform login
  $service = new Services_Twitter('indigozero', 'guessme');
  
  // update status
  $service->statuses->update('Having dinner with friends');
   
  // perform logout
  $service->account->end_session();
} catch (Exception $e) { 
  die('ERROR: ' . $e->getMessage());
}
?>

The Services_Twitter package contains separate sub-classes, or “drivers”, for different areas of the Twitter API. For example, there’s a Services_Twitter_Statuses class for status manipulation, and a Services_Twitter_Account class for user account manipulation. These sub-classes are “lazily loaded” by the main Services_Twitter class as needed.

Looking at the example above, it’s clear then that the first order of business is to include the Services_Twitter class file and create a new Services_Twitter object, $service, which represents a Twitter API client. Passing the object constructor a valid Twitter user name and password initializes the client. Once initialized, the call to $service->statuses->update() method loads the Services_Twitter_Statuses sub-class and invokes its update() method, which creates and transmits a POST request to the Twitter server. At the Twitter end of things, the Twitter server receives this POST request, verifies the user authentication credentials, and updates the user’s status to reflect the new value. The $service->account->end_session() call then terminates the user session.

You can also make this a little more fun, by presenting users with a Web form that allows them to interactively update their status on the Twitter Web site. Here’s the code:

<html>
  <head></head>
  <body>
    <h2>Update Twitter Status</h2>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Username: <br/>
      <input type="text" name="user" /><br/>
      Password: <br/>
      <input type="password" name="pass" /><br/>
      New status message: <br/>
      <textarea name="status" cols="15"></textarea><br/>
      <input type="submit" name="submit" value="Update Status" />      
    </form>
    </form>
    <?php
    } else {
      // include class
      include_once 'Services/Twitter.php';
      try {
        // read form input
        $user = $_POST['user'];
        $pass = $_POST['pass'];
        $status = $_POST['status'];
        
        // initialize service object
        $service = new Services_Twitter($user, $pass);
        
        // update status
        $service->statuses->update($status);
        
        // perform logout
        $service->account->end_session();        
        echo 'Status updated!';
      } catch (Exception $e) { 
        die('ERROR: ' . $e->getMessage());
      }
    }
    ?>
  </body>
</html>

This script is divided into two parts, separated by a conditional test which checks if the form has been submitted or not. If not, a simple HTML form, with fields for the user’s Twitter screen name, password and status message is generated. On submission, the second half of the script comes into play: it loads the Services_Twitter client, uses the supplied credentials to log in to the Twitter Web site, and updates the user’s status message as described for the previous listing.

Here are some images showing this script in action:



Once submitted, the revised status should also be visible on the user’s Twitter page:

When using the Services_Twitter package with the Twitter API, there are a few important things to keep in mind:

  1. The Twitter API currently supports HTTP Basic authentication as its authentication scheme. However, OAuth support is currently being tested and should be out of beta shortly. When this happens, the Services_Twitter package will also be updated to use this authentication scheme.
  2. The Twitter API uses HTTP response codes to indicate whether a particular request succeeded or failed. The Services_Twitter package already knows about these error codes, and will automatically parse response packets, retrieve error messages and turn them into PEAR-compliant exceptions, which can be caught using standard try-catch blocks.
  3. The Twitter API can produce output in both XML and JSON formats, but the Services_Twitter package defaults to XML. The exception to this is the Twitter Search API, which currently produces output only in Atom and JSON formats; here, Services_Twitter defaults to JSON. You’ll see an example of using the Twitter Search API with the Services_Twitter package a little further along in this tutorial.
  4. Twitter allows API clients only 100 requests per hour. You can request a higher limit by writing to Twitter administrators with details of your application.

Passing Time

In addition to posting new status updates, the Services_Twitter package also allows developers to retrieve previously-posted updates by the authenticating user, via the Services_Twitter_Statuses::user_timeline() method. Here’s an example:

<html>
  <head>
    <style>
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
  </style>
  </head>
  <body>
    <h2>My recent status updates</h2>
    <?php
    // include class
    include_once 'Services/Twitter.php';
    
    try {
      // initialize service object
      // perform login
      $service = new Services_Twitter('indigozero', 'guessme');
      
      // get status updates posted by logged-in user
      // display as list
      $response = $service->statuses->user_timeline();  
      if (count($response->status) > 0) {
        foreach ($response->status as $status) {
          echo '<div class="item">';
          echo $status->text . '<br/>';
          echo 'By: <em>' . $status->user->screen_name . '</em> on ' . $status->created_at . '</div>';
        }
      }
      
      // perform logout
      $service->account->end_session();
    } catch (Exception $e) { 
      die('ERROR: ' . $e->getMessage());
    }
    ?>
  </body>
</html>

Here, the user_timeline() method generates a list of the 20 most recent status updates for the logged-in user. This list can easily be processed as an array of SimpleXML elements using a foreach() loop. In particular, take note of the $status->text, $status->user->screen_name and $status->created_at properties, which represent the status message, account name and status update time respectively.

Here’s a sample of what the output looks like:

Two alternatives to the user_timeline() method are the friends_timeline() method, which returns the 20 most recent status updates by the logged-in user and his/her friends, and the public_timeline() method, which returns the 20 most recent public status updates. Here’s an example of these methods in use:

<html>
  <head>
    <style>
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
    .img {
      float:left;
      margin-right:1em; 
      padding-bottom: 10px;
      height: 48px;
      width: 48px;
    }
    </style>
  </head>
  <body>
    <?php
    // include class
    include_once 'Services/Twitter.php';
    
    try {
      // initialize service object
      $service = new Services_Twitter('indigozero', 'guessme');
      
      // get status updates posted by logged-in user and friends
      $response = $service->statuses->friends_timeline();  
      if (count($response->status) > 0) {
        echo '<h2>Recent status updates</h2>';
        foreach ($response->status as $status) {
            echo '<div class="item"><img src="' . $status->user->profile_image_url . '" class="img" />';
            echo $status->text . '<br/>';
            echo 'By: <em>' . $status->user->screen_name . '</em> on ' . $status->created_at . '</div>';
        }
      }
      
      // get recent posts on public timeline
      $response = $service->statuses->public_timeline();  
      if (count($response->status) > 0) {
        echo '<h2>Recent public timeline updates</h2>';
        foreach ($response->status as $status) {            
            echo '<div class="item"><img src="' . $status->user->profile_image_url . '" class="img" />';
            echo $status->text . '<br/>';
            echo 'By: <em>' . $status->user->screen_name . '</em> on ' . $status->created_at . '</div>';
        }
      }
            
      // perform logout
      $service->account->end_session();
    } catch (Exception $e) { 
      die('ERROR: ' . $e->getMessage());
    }
    ?>
  </body>
</html>

Notice that this listing also makes use of the $status->user->profile_image_url property, to display a thumbnail image of the user’s profile picture in the output. Here’s what it looks like:



Follow The Leader

Twitter makes a distinction between “friends” – the users you follow – and “followers” – the users following you. And Twitter’s API makes it possible to programmatically obtain listings of both your friends and followers, together with their current status. This capability is replicated in the Services_Twitter package, via the Services_Twitter_Statuses::friends() and Services_Twitter_Statuses::followers() methods. To illustrate these methods, consider the following listing, which displays the currently logged-in user’s friends and followers, together with their current status and profile image:

<html>
  <head>
    <style>
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
    .img {
      float:left;
      margin-right:1em; 
      padding-bottom: 10px;
      height: 48px;
      width: 48px;
    }
    </style>
  </head>
  <body>
    <?php
    // include class
    include_once 'Services/Twitter.php';
    
    try {
      // initialize service object
      $service = new Services_Twitter('indigozero', 'guessme');

      // get friends listing
      $response = $service->statuses->friends();
      if (count($response->user) > 0) {
        echo '<h2>My Friends</h2>';
        foreach ($response->user as $user) {
            echo '<div class="item"><img src="' . $user->profile_image_url . '" class="img" />';
            echo $user->name . ' (@' . $user->screen_name . ')<br/>';
            $status = (trim($user->status->text) != '') ? $user->status->text : 'No status information';
            echo '<em>' . $status . '</em></div>';
        }
      }
      
      // get followers listing
      $response = $service->statuses->followers();
      if (count($response->user) > 0) {
        echo '<h2>My Followers</h2>';
        foreach ($response->user as $user) {
            echo '<div class="item"><img src="' . $user->profile_image_url . '" class="img" />';
            echo $user->name . ' (@' . $user->screen_name . ')<br/>';
            $status = (trim($user->status->text) != '') ? $user->status->text : 'No status information';
            echo '<em>' . $status . '</em></div>';
        }
      }
                  
      // perform logout
      $service->account->end_session();
    } catch (Exception $e) { 
      die('ERROR: ' . $e->getMessage()); 
    }
    ?>
  </body>
</html>

The return value of the friends() and followers() methods is a collection of objects, each representing a Twitter user. It’s easy to access information about each of these users from the various object properties, as shown above. Here’s what the output might look like:

You can also obtain another Twitter user’s friends, by passing the target’s screen name to the friends() method using the ‘id’ parameter. Consider the next example, which illustrates by setting up a Web form that lets you view any Twitter user’s friends:

<html>
  <head>
    <style>
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
    .img {
      float:left;
      margin-right:1em; 
      padding-bottom: 10px;
      height: 48px;
      width: 48px;
    }
    </style>
  </head>
  <body>
    <h2>Find Friends on Twitter</h2>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      <input type="text" name="username" /><br/>
      <input type="submit" name="submit" value="Find Friends" />      
    </form>
    <?php
    } else {
      // include class
      include_once 'Services/Twitter.php';
      try {
        // read form input
        $user = $_POST['username'];
        
        // initialize service object
        $service = new Services_Twitter(null, null);
        
        // get friend listing for target user
        $response = $service->statuses->friends(array('id' => $user));
        if (count($response->user) > 0) {
          echo '<h2>' . $user . '\'s Friends</h2>';
          foreach ($response->user as $user) {
              echo '<div class="item"><img src="' . $user->profile_image_url . '" class="img" />';
              echo $user->name . ' (@' . $user->screen_name . ')<br/>';
              $status = (trim($user->status->text) != '') ? $user->status->text : 'No status information';
              echo '<em>' . $status . '</em></div>';
          }
        }
        
        // perform logout
        $service->account->end_session();
      } catch (Exception $e) { 
        die('ERROR: ' . $e->getMessage());
      }
    }
    ?>
  </body>
</html>

Here’s what the form looks like:

When this form is submitted, the screen name supplied by the user is passed to the friends() method in an “options” array. The method then queries the Twitter API for this user’s friends and displays a neat listing, as shown below:

You can build a similar form to interactively list any user’s followers (note that this requires authentication):

<html>
  <head>
    <style>
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
    .img {
      float:left;
      margin-right:1em; 
      padding-bottom: 10px;
      height: 48px;
      width: 48px;
    }
    </style>
  </head>
  <body>
    <h2>Find Followers on Twitter</h2>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Username: <br/>
      <input type="text" name="user" /><br/>
      Password: <br/>
      <input type="password" name="pass" /><br/>
      Followers of: <br/>
      <input type="text" name="target" /><br/>
      <input type="submit" name="submit" value="Find Followers" />      
    </form>
    <?php
    } else {
      // include class
      include_once 'Services/Twitter.php';
      try {
        // read form input
        $user = $_POST['user'];
        $pass = $_POST['pass'];
        $target = $_POST['target'];
        
        // initialize service object
        $service = new Services_Twitter($user, $pass);
        
        // get follower listing for target user
        $response = $service->statuses->followers(array(), $target);
        if (count($response->user) > 0) {
          echo '<h2>' . $target . '\'s Followers</h2>';
          foreach ($response->user as $user) {
              echo '<div class="item"><img src="' . $user->profile_image_url . '" class="img" />';
              echo $user->name . ' (@' . $user->screen_name . ')<br/>';
              $status = (trim($user->status->text) != '') ? $user->status->text : 'No status information';
              echo '<em>' . $status . '</em></div>';
          }
        }
        
        // perform logout
        $service->account->end_session();
      } catch (Exception $e) { 
        die('ERROR: ' . $e->getMessage());
      }
    }
    ?>
  </body>
</html>

Here, the target user’s screen name is provided to the followers() method as second argument. Here’s an example of the form and result page:



Developers can also use the Services_Twitter package to generate follower relationships between Twitter user, by invoking the Services_Twitter_Friendships::create() method. Consider the following example, which creates a Web form similar to that of the previous example and initiates a follower relationship between the logged-in user and the specified target user:

<html>
  <head>
    <style>
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
    .img {
      float:left;
      margin-right:1em; 
      padding-bottom: 10px;
      height: 48px;
      width: 48px;
    }
    </style>
  </head>
  <body>
    <h2>Follow Someone on Twitter</h2>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Username: <br/>
      <input type="text" name="user" /><br/>
      Password: <br/>
      <input type="password" name="pass" /><br/>
      Follow: <br/>
      <input type="text" name="target" /><br/>
      <input type="submit" name="submit" value="Follow!" />      
    </form>
    <?php
    } else {
      // include class
      include_once 'Services/Twitter.php';
      try {
        // read form input
        $user = $_POST['user'];
        $pass = $_POST['pass'];
        $target = $_POST['target'];
        
        // initialize service object
        $service = new Services_Twitter($user, $pass);
        
        // follow target user
        $service->friendships->create($target);
        
        // perform logout
        $service->account->end_session();
        echo 'Added user @' . $target . ' to your follow list';
      } catch (Exception $e) { 
        die('ERROR: ' . $e->getMessage());
      }
    }
    ?>
  </body>
</html>

There’s also a Services_Twitter_Friendships::destroy() method, which can be used to remove a follower relationships.

The Direct Approach

The Twitter API supports sending direct messages between a user and his/her followers. Here’s an example of how you can leverage this feature and build it into your own application, using the Services_Twitter_DirectMessages::new() method:

<html>
  <head>
  </head>
  <body>
    <h2>Send Direct Messages on Twitter</h2>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Username: <br/>
      <input type="text" name="user" /><br/>
      Password: <br/>
      <input type="password" name="pass" /><br/>
      Recipient: <br/>
      <input type="text" name="to" /><br/>
      </select>
      Direct message: <br/>
      <textarea name="message" cols="15"></textarea><br/>
      <input type="submit" name="submit" value="Send" />      
    </form>
    <?php
    } else {
      try {
        // include class
        include_once 'Services/Twitter.php';

        // read form input
        $user = $_POST['user'];
        $pass = $_POST['pass'];
        $to = $_POST['to'];
        $message = $_POST['message'];
        
        // initialize service object
        $service = new Services_Twitter($user, $pass);

        // create and send direct message to recipient
        $service->direct_messages->new($to, $message);
        
        // perform logout
        $service->account->end_session();
        echo 'Your message was sent!';
      } catch (Exception $e) { 
        die('ERROR: ' . $e->getMessage());
      }
    }
    ?>
  </body>
</html>

This script generates a Web form that asks for your Twitter user credentials, the name of the follower to whom you wish to send a message, and the message body. On submission, the script will attempt to send a direct message to the specified user via the Services_Twitter_DirectMessages::new() method, which accepts two arguments: the recipient’s Twitter username, and the message body.

Here’s an example of the form, and the result when the message is successfully sent:



Note that if you enter the name of a user who is not following you, Twitter will disallow your message with an error code, an exception will be raised in the script, and you’ll end up with an error like the one below:

You can also obtain a list of the 20 most recent direct messages sent by and to the logged-in user with the Services_Twitter_DirectMessages::sent() and Services_Twitter::direct_messages() methods respectively. Here’s an example illustrating these methods in use:

<html>
  <head>
    <style>
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
    .img {
      float:left;
      margin-right:1em; 
      padding-bottom: 10px;
      height: 48px;
      width: 48px;
    }
    </style>
  </head>
  <body>
    <h2>View Direct Messages on Twitter</h2>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Username: <br/>
      <input type="text" name="user" /><br/>
      Password: <br/>
      <input type="password" name="pass" /><br/>
      <input type="submit" name="submit" value="See Messages" />      
    </form>
    <?php
    } else {
      try {
        // include class
        include_once 'Services/Twitter.php';
    
        // read form input
        $user = $_POST['user'];
        $pass = $_POST['pass'];
        
        // initialize service object
        $service = new Services_Twitter($user, $pass);

        // get list of sent direct messages
        $sent = $service->direct_messages->sent();
        if (count($sent->direct_message) > 0) {
          echo '<h2>Sent Messages</h2>';
          foreach ($sent->direct_message as $msg) {
              echo '<div class="item"><img src="' . $msg->recipient->profile_image_url . '" class="img" />';
              echo 'To: ' . $msg->recipient->name . ' (@' . $msg->recipient->screen_name . ') on ' . $msg->created_at . '<br/>';
              echo '<em>' . $msg->text . '</em></div>';
          }
        } 
      
        // get list of received direct messages 
        $received = $service->direct_messages();
        if (count($received->direct_message) > 0) {
          echo '<h2>Received Messages</h2>';
          foreach ($received->direct_message as $msg) {
              echo '<div class="item"><img src="' . $msg->sender->profile_image_url . '" class="img" />';
              echo 'From: ' . $msg->sender->name . ' (@' . $msg->sender->screen_name . ') on ' . $msg->created_at . '<br/>';
              echo '<em>' . $msg->text . '</em></div>';
          }
        }
                
        // perform logout
        $service->account->end_session();
      } catch (Exception $e) { 
        die('ERROR: ' . $e->getMessage());
      }
    }
    ?>
  </body>
</html>

In both cases, each direct message object returned by Twitter contains two nested user objects, one each for the sender and recipient, in addition to the message text. The example above illustrates how these nested objects can be used to retrieve sender and recipient information. Here’s what the output might look like:

You can also get a list of the 20 most recent mentions (tweets containing the authenticating user’s screen name) by invoking Services_Twitter_Statuses::mentions(). This method isn’t explicitly defined in the Services_Twitter package; however, through the power of the __call() “magic method”, Services_Twitter will intelligently determine the URL endpoint for the method in the Twitter API and present the results. Here’s the code:

<html>
  <head>
    <style>
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
    .img {
      float:left;
      margin-right:1em; 
      padding-bottom: 10px;
      height: 48px;
      width: 48px;
    }
    </style>
  </head>
  <body>
    <?php
    // include class
    include_once 'Services/Twitter.php';
    
    try {
      // initialize service object
      $service = new Services_Twitter('indigozero', 'guessme');
      
      // get mentions
      $response = $service->statuses->mentions();
      if (count($response->status) > 0) {
        echo '<h2>Recent Mentions</h2>';
        foreach ($response->status as $status) {
            echo '<div class="item"><img src="' . $status->user->profile_image_url . '" class="img" />';
            echo $status->user->name . ' (@' . $status->user->screen_name . ')<br/>';
            $body = (trim($status->text) != '') ? $status->text : 'No status information';
            echo '<em>' . $body . '</em></div>';
        }
      }
      
      // perform logout
      $service->account->end_session();
    } catch (Exception $e) { 
      die('ERROR: ' . $e->getMessage());
    }
    ?>
  </body>
</html>

Searching For Godot

Twitter also offers a Search API, which can be used to find tweets matching a given term and which makes it easy to integrate Twitter search results into your application. This Search API is currently distinct from the “regular” Twitter API you’ve seen in previous examples (although plans are underway to merge the two) and currently produces output only in Atom and JSON formats. Don’t let that bother you too much, though – the Services_Twitter package can handle JSON output without breaking a sweat!

Here’s an example of retrieving Twitter’s top 10 trends at any given moment, using the Services_Twitter_Search::trends() method:

<html>
  <head></head>
  <body>
    <?php
    // include class
    include_once 'Services/Twitter.php';
    
    try {
      // initialize service object
      $service = new Services_Twitter(null, null);
      
      // get 10 most recent trends
      $response = $service->search->trends();  
      if (count($response->trends) > 0) {
        echo '<h2>Recent Trends</h2>';
        echo '<ul>';        
        foreach ($response->trends as $trend) {
            echo '<li><a href="' . $trend->url . '">' . $trend->name . '</a></li>';
        }
        echo '</ul>';
      }      
            
      // perform logout
      $service->account->end_session();
    } catch (Exception $e) { 
      die('ERROR: ' . $e->getMessage());
    }
    ?>
  </body>
</html>

And here’s an example of the output:

Retrieving tweets matching a particular query term is equally simple – just pass the query term to the Services_Twitter_Search::query() method, and iterate over the resulting object collection. Here’s an example, which builds an interactive search form and, on submission, searches Twitter for the input term:

<html>
  <head>
    <style>
    .item {
      float:none;
      clear:both;
      margin-top:1em;  
    }
    .img {
      float:left;
      margin-right:1em; 
      padding-bottom: 10px;
      height: 48px;
      width: 48px;
    }
    </style>
  </head>
  <body>
    <h2>Search Twitter</h2>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
      Search for: <br/>
      <input type="text" name="q" /><br/>
      <input type="submit" name="submit" value="Search!" />      
    </form>
    <?php
    } else {
      // include class
      include_once 'Services/Twitter.php';
      try {
        // read form input
        $q = urlencode($_POST['q']);
        
        // initialize service object
        $service = new Services_Twitter(null, null);
        
        // search for matching tweets
        $response = $service->search->query($q);
        if (count($response->results) > 0) {
          echo '<h2>Search results for \'' . $q . '\'</h2>';          
          foreach ($response->results as $result) {
            echo '<div class="item"><img src="' . $result->profile_image_url . '" class="img" />';
            echo $result->text . '<br/>';
            echo 'By: <em>' . $result->from_user . '</em> on ' . $result->created_at . '</div>';
          }
        }      
              
        // perform logout
        $service->account->end_session();
      } catch (Exception $e) { 
        die('ERROR: ' . $e->getMessage());
      }
    }
    ?>
  </body>
</html>

Here’s an example of the results obtained when searching for ‘godot’:

Note that the Twitter Search API supports a variety of optional modifiers that can be used to filter the result set, such as the language ('lang') or location ('geocode'). However, these modifiers are not currently supported by the Services_Twitter_Search::query() method.

These examples are just the tip of the iceberg: the Services_Twitter package includes support for various other aspects of the Twitter experience, including adding and removing favorites, viewing extended user information, and changing account settings. The package’s well-defined interface to the Twitter API takes the pain out of directly formulating and executing REST queries, and it can significantly reduce the drudge work of integrating Twitter into your application. As such, it’s a valuable addition to any programmer’s toolkit, and one that you should definitely take some time out to experiment with. Take a look at it sometime, and see what you think!

Copyright Melonfire, 2009. All rights reserved.

24 Responses to “Using the Twitter API with PHP and PEAR”

  1. karoo1288 Says:

    I wanna say dis is excellent tutorial
    I hav an error naming ERROR: Unauthorized even i m using a correct username and password
    can u help me in that??

  2. fbraiman Says:

    <html>
    <head></head>
    <body>
    <h2>Update Twitter Status</h2>
    <?php
    if (!isset($_POST['submit'])) {
    ?>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
    Username: <br/>
    <input type="text" name="user" /><br/>
    Password: <br/>
    <input type="password" name="pass" /><br/>
    New status message: <br/>
    <textarea name="status" cols="15"></textarea><br/>
    <input type="submit" name="submit" value="Update Status" />
    </form>
    </form>
    <?php
    } else {
    // include class
    include_once ‘Services/Twitter.php’;
    try {
    // read form input
    $user = $_POST['user'];
    $pass = $_POST['pass'];
    $status = $_POST['status'];

    // initialize service object
    $service = new Services_Twitter($user, $pass);

    // update status
    $service->statuses->update($status);

    // perform logout
    $service->account->end_session();
    echo ‘Status updated!’;
    } catch (Exception $e) {
    die(‘ERROR: ‘ . $e->getMessage());
    }
    }
    ?>
    </body>
    </html>
    when i run the above code i got the below errors

    Warning: require_once(PEAR/Exception.php) [function.require-once]: failed to open stream: No such file or directory in E:\wamp\www\signIN\Services\Twitter\Exception.php on line 46

    Fatal error: require_once() [function.require]: Failed opening required ‘PEAR/Exception.php’ (include_path=’.;C:\php5\pear’) in E:\wamp\www\signIN\Services\Twitter\Exception.php on line 46

  3. incomsis Says:

    Great article, thanks!

    Dimitar @ http://winbigmoneyonline.com/

  4. cowwen Says:

    Hi. can i just check with you how do i go about doing the service/twitter.php?
    can anyone help me out with it?
    thanks alot

    regards,
    cowwen

  5. rgenzonn Says:

    Hi, just wanted to know if you have a demo page for this one or maybe a file that has everything on it already? I’m new to PHP and I wanna know more about this. Please help me. If you can post a compressed file for this great tutorial, it would be great

  6. interberry Says:

    Hi,
    I need to see my total number of friends and followers. But this api limit the total followers/friends as 100. How can i get all my friends. Pls help me

    visit – Services/Twitter/Statuses.php

    /**
    * Returns up to 100 of the user’s friends
    *
    * @param array $params Parameters array
    *
    * @return object Instance of SimpleXMLElement of new status
    * @throws Services_Twitter_Exception
    * @see Services_Twitter_Common::sendRequest()
    */

  7. trumpetwebsites Says:

    Ok the above error with the search is fixed due to the following PEAR package update:

    $twitter->search->query() has been replaced by $twitter->search() (you can also write $twitter->search->search())

    http://www.trumpetmouth.com.au

  8. trumpetwebsites Says:

    When trying to use the Search API on my local machine I get the following error:

    ERROR: Unsupported endpoint search/query

    I am guessing that this has something to do with the way my router is set up. Does anyone have any clues?

    Thanks
    Oliver

  9. nightmare49 Says:

    Excellent tutorial, hey can any give me the code to get the list of "Following" of the users.
    Kindly mail the to pgssoftwares@gmail.com.

    Thank you in advance.

  10. aljosja84 Says:

    I’m having an issue as well; the first example works like a charm. From there on nothing seems to work anymore. No errors, just nothing. Did I miss something?

  11. lab69 Says:

    I ran the first script of this tutorial and worked correctly, i could update my status… but the second and third don’t work, i run the script but i see nothing, no messages, no errors.

    whats happening?

    Thanks in advance.

  12. danallen_vt Says:

    100% of what I need. Completely all laid out.

    Of course, I feel like the class slow poke, because I am stuck on the assumption regarding installing the Twitter_Services package from the PEAR website. Now I am on the phone with my friends at Godaddy, and they are checking up the line to see whether I can install with the pear installer on my shared linux hosting account. I do know curl is on there, because I use it already for posting updates to Twitter.

    Just passing along the situation, so other encountering it will know they are not alone.

  13. bendriss Says:

    Hello,
    first of all thank you for the article : clear and well written.
    I requested fro twitter to remove limitations on my account, and I can see it is ok, but when I run the script for example to get my friends list, I only get 100 accounts.
    Is there any setting I have to do?
    thank you again and in advance for any answer.

    Regards,

  14. _____anonymous_____ Says:

    Would the licensing on this product prohibit such an application.
    I like the setup/interface and would be willing to pay for a specific rights free version.
    You can reach me @victusfate on twitter

  15. _____anonymous_____ Says:

    Hello Vikram

    Its really a nice package to use. I want to use if for the PHP 5.1.x. Can you please tell me whether its possible to have Services_Twitter for PHP 5.1.x?

    Thanks

  16. amrigo Says:

    What more can be said? great tutorial! i will follow for the next one.

  17. Myfacefriends Says:

    i want to say thank you for this tutorial…. very good indeed..
    http://myfacefriends.com

  18. _____anonymous_____ Says:

    Although this class is awesome, it does not have the option to check for "Friendship exists" (at least I couldn’t find a way)

    So I changed the script a little bit so it can check for that… Now keep in mind that I am not all familiar with php classes, so I am sure there’s a better way to code this, but it works for me…

    1. Friendships.php

    I added a third case on line 87 right before "default case".

    case ‘exists’:

    return $this->sendRequest(
    ‘/friendships/’ . $function . ‘.xml?user_a=’ . $args[0] . ‘&user_b=’ . $args[1], array(), ‘GET’
    );

    break;

    2. Common.php

    You need to fix common.php to remove the "xml" from the end of the string because it’s a GET method, not a POST

    So I added this inside the "else" online 174 to check for the string "exists"

    if(strstr($endPoint,"exists")) {

    $uri = Services_Twitter::$uri . $endPoint;

    }

    else{

    $uri = Services_Twitter::$uri . $endPoint . ‘.xml’;

    }

    And last you just call it this way:

    $service = new Services_Twitter(”,”);
    $service->friendships->exists($user_a,$user_b);

    It will return true or false.

    Maybe that will help someone…

    Dan @swagcodes.com

  19. _____anonymous_____ Says:

    I get a fatal error if authentication doesn’t go through.. how can I handle erros? I don’t fatal erros, but instead printing some other message.

    Uncaught Could not authenticate you. (Code: 1, Call: http://twitter.com/statuses

  20. jess04 Says:

    @rmurdo

    Make sure include_path [set in php.ini or another INI in your scandir] includes the path to the pear include files, probably, /usr/share/pear in your case.

  21. rmurdo Says:

    Hi,

    I installed the pear stuff for twitter per the turotial.

    Its in /usr/share/pear/

    However, I cant seem to get to it with my scripts!

    Fri Apr 24 19:46:47 2009] [error] [client 205] PHP Warning: include_once(Services/Twitter.php) [<a href='function.include-once'>function.include-once</a>]: failed to open stream: No such file or directory in /var/www/vhosts/robscripts.com/httpdocs/work/twitter/1.php on line 21
    [Fri Apr 24 19:46:47 2009] [error] [client 205] PHP Warning: include_once() [<a href='function.include'>function.include</a>]: Failed opening ‘Services/Twitter.php’ for inclusion (include_path=’.:/usr/share/pear’) in /var/www/vhosts/robscripts.com/httpdocs/work/twitter/1.php on line 21
    [Fri Apr 24 19:46:47 2009] [error] [client 205] PHP Fatal error: Class ‘Services_Twitter’ not found in /var/www/vhosts/robscripts.com/httpdocs/work/twitter/1.php on line 25

    As you can see, I added the dir to the path, still didnt work.

    Any ideas on how I need to configure this? Thanks!

  22. _____anonymous_____ Says:

    where is the file "Services/Twitter.php". Pls help me.

    Thanks,
    Prabhu

  23. makingmemark Says:

    Many thanks for the tutorial, very informative

  24. _____anonymous_____ Says:

    I search a long time and now i am find a very good tutorial. Thanks ;)