본문 바로가기
프로그래밍/PHP

Twitter OAuth for PHP

by o테리o 2011. 5. 10.

The Open Source minefield

Whilst I am a huge fan of open source, one of the downsides is it can be extremely hard to find definitive information detailing which versions of packages work with each other. Documentation in general is rather patchy. Using google to search for error messages is a good way of navigating some of the pain, but good and bad advice seems to exist in equal quantities!

OAuth is now required for Twitter

In August 2010 Twitter deprecated its basic authentication method, and my RSS aggregator/twitterbot stopped working. It was thus urgent that I update the code to use OAuth. I found a very useful article on Making a Twitter/OAuth PHP robot which helped a lot in the process, but almost immediately I hit a problem.

Setting up OAuth for PHP 5.1.6

The article say that the following is required.

yum install php-devel
yum install libcurl-devel
pecl install -R /usr/lib/php oauth-0.99.9

The first is fine but neither of the next two worked for me. Centos 5.3 says No package libcurl-devel available. After a bit of digging around I found that I actually needed to do

yum install curl-devel

Secondly when using pecl to install oauth I get

Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 92160 bytes) in /root/PEAR/PEAR/PackageFile/v2/Validator.php on line 912

This is because PECL ignores the memory allocation set in php.ini. General advice is to use peardev install instead of pecl (eg peardev install pecl/oauth). I generally do not use version numbers when installing because you never really know how out of date an article is. When using yum this is fine as centos picks the right version for you. Unfortunately peardev install is not so clever and that lead to the following error:

/usr/share/pear/temp/oauth/php_oauth.h:47:31: error: ext/pcre/php_pcre.h: No such file or directory

Some sites I found indicate that to get around thus you need PHP 5.2.2. But Centos does not support that. Fortunately trying again with the version number it works just fine.

So my revised command list is

yum install php-devel
yum install curl-devel
peardev install pecl/oauth-0.99.9

After adding extension=oauth.so to /etc/php.d/oauth.ini and restarting Apache I was ready to play with OAuth.

Using a Single Access Token with Twitter

The Twitter API manual notes that for single user applications a single access token may be used as an alternative to implementing the full OAuth token acquisition dance. Twitter's PHP documentation, however, assumes that you are using @abraham's PHP twitteroauth Library. I already have my own twitter library, so rather than relearn how to do all the API calls with someone else's library I elected to retrofit the OAUth authentication to my code. Given that Twitter neglects documenting it in raw PHP here are a few lines from my Twitter API to show just how easy it can be. Note that for full production code more rigorous error testing is recommended!

<?php
class myTwitter
  {
  public  $httpStatus;
  public  $errText;
  public  $verbose=true; 
 
  # The following keys are on the Applications Details page in Twitter
  private $consumer_key = '####';
  private $consumer_secret = '####';
 
  # The following keys are on the 'My access token' page in Twitter
  # As Gandalf would say "Keep them Secret, keep them safe"
  private $access_token = '####';
  private $access_token_secret = '###';
 
  private $oa;
 
  public function __construct()
  {
  $this->oa = new OAuth($consumer_key,$consumer_secret,
                        OAUTH_SIG_METHOD_HMACSHA1,OAUTH_AUTH_TYPE_URI);
  if ($this->oa)
    $this->oa ->setToken($access_token, $access_token_secret);
  }
 
  private function MakeAPICall($twitter_url, $post=false, $args=null)
  {
  $xml="";
 
  if ($this->oa)
    {
    if ($post) $this->oa->fetch($twitter_url,$args, OAUTH_HTTP_METHOD_POST );
    else $this->oa->fetch($twitter_url,null, OAUTH_HTTP_METHOD_GET); 
 
    $status = $this->oa->getLastResponseInfo();
    $this->httpStatus =  $status['http_code'];
 
    $xml = simplexml_load_string($this->oa->getLastResponse());
 
    if ($this->httpStatus != 200)
      {
      $this->errText = $xml->error;
      if ($this->verbose) echo "$this->httpStatus: $xml->error<br />\n";
      }
    else $this->errText= "OK";
    }
  return $xml;
  }
 
  public function Tweet($text)
  {
  $this->MakeAPICall ("http://twitter.com/statuses/update.xml",
                       true, array("status"=>$text));
 
  return $this->httpStatus;
  }
}
 
$tw = new myTwitter();
$tw->Tweet("Hello all you happy people");