I promised more programming related posts, and here’s one for you.
As part of developing TweeterDiet.com, I needed to interface with Twitter and Bit.ly to post tweets and the links back to the public profiles on TweeterDiet. I searched around for a while, and didn’t immediately run across any good components for what I needed, so I wrote my own, and now I’d like to share them.
Up first, the Twitter Component. This relies on the EpiTwitter class from the twitter-async project on GitHub.
app/controllers/components/twitter.php:
class TwitterComponent extends Object { function __construct() { require_once(APP.'vendors/twitter-async/EpiCurl.php'); require_once(APP.'vendors/twitter-async/EpiOAuth.php'); require_once(APP.'vendors/twitter-async/EpiTwitter.php'); $this->twitterObj = new EpiTwitter(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET); App::Import('Component', 'Bitly'); $this->Bitly = new BitlyComponent(); } function sendTweet($text, $url = null) { if ($url !== null) { $url = ' '.$this->Bitly->shorten($url); } $message = trim($text . $url); if (strlen($message) > 140) { return false; } else { try { $this->twitterObj->post_statusesUpdate(array('status' => $message)); } catch (Exception $e) { return false; } return true; } } function __call($name, $arguments) { return call_user_func_array(array($this->twitterObj, $name), $arguments); } }
This class expects you to define your app’s Twitter oAuth Consumer Key and Consumer Secret as constants. Here’s an example of how to do it:
app/config/bootstrap.php:
define('TWITTER_CONSUMER_KEY', 'KEY_HERE'); define('TWITTER_CONSUMER_SECRET', 'SECRET_HERE');
The Twitter component also relies on the Bit.ly component I wrote along with it, for doing URL shortening. Here’s the source code for it:
app/controllers/components/bitly.php:
class BitlyComponent extends Object { var $user; var $api_key; function __construct() { $this->user = BITLY_USER; $this->api_key = BITLY_API_KEY; $this->BitlyLink = ClassRegistry::init('BitlyLink'); } function setApiInfo($user, $api_key) { $this->user = $user; $this->api_key = $api_key; } function shorten($long_url) { $cache = $this->BitlyLink->find('first', array('conditions' => array('BitlyLink.long_url' => $long_url))); if (!empty($cache['BitlyLink']['id'])) { return 'http://bit.ly/'.$cache['BitlyLink']['hash']; } $params = array(); $params['login'] = $this->user; $params['apiKey'] = $this->api_key; $params['version'] = '2.0.1'; $params['format'] = 'json'; $params['longUrl'] = $long_url; $url = 'http://api.bit.ly/shorten?'.http_build_query($params); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $data = curl_exec($ch); curl_close($ch); $data = json_decode($data, true); if ($data['errorCode'] == 0) { $result = array_pop(array_values($data['results'])); $save = array('BitlyLink' => array()); $save['BitlyLink']['long_url'] = $long_url; $save['BitlyLink']['hash'] = $result['userHash']; $this->BitlyLink->create(); $this->BitlyLink->save($save); return $result['shortUrl']; } else { return false; } } }
This class expects two constants to be defined as well:
app/config/bootstrap.php
define('BITLY_USER', 'USER'); define('BITLY_API_KEY', 'API_KEY');
It also expects a model for caching the links so that it won’t have to send multiple requests for the same URL. Here’s the schema for that model:
BitlyLink Model:
CREATE TABLE IF NOT EXISTS `bitly_links` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `long_url` VARCHAR(255) NOT NULL, `hash` VARCHAR(255) NOT NULL, `created` datetime DEFAULT NULL, `updated` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `long_url` (`long_url`) );
That about wraps it up. I use these two Components in TweeterDiet to help me with my communication to Twitter and Bitly. I hope they help someone else as well. If you have any questions, please post them below, and I’ll do what I can to help you.
Thanks man. Big up. Clean and neat code!
I’m trying to make a component in this manner using the same twitter-async lib for signing in with Twitter, but when I call the getAuthenticateUrl function in my view where I’ve set the twitterObj it says that it’s undefined
Without code to look at, there’s no way to troubleshoot the problem. I’d suggest talking with the people in the #cakephp channel on Freenode. They’ll ask you to put the code up in a pastebin for them to look at.
Well if you don’t mind checking the code you can see here http://stackoverflow.com/questions/6988180/cakephp-twitter-component