【Twitter API, CakePHP, Ajax】since_idを使わずに新着ツイートを取得

twitterの検索関連のAPIsince_id廃止予定だそうです。
そのせいなのかどうなのか、キテるタグで、新着ツイートを
うまく取得できないことがたびたびありました。


//hogeを含むツイートの中で、idが1234より大きなものだけを取得
http://search.twitter.com/search.json?q=hoge&since_id=1234


id:1234 こんにちは ←現在、最も新しいツイート
id:1233 おはよう
id:1232 おやすみ
...

『since_id=1234』なら、1234より大きな値のidのツイートだけを取得できるはずなのに…

そこで、新着ツイートの取得に別の方法を取ることにしました。


【処理の流れ】
  1. 現在最も新しいツイートのidを保存しておく。

  2. すでに取得したツイートと重複しても構わないので、新しいものから順に

    ツイートを検索APIの1回の限度いっぱいの100件取得。
  3. 保存したidよりも大きなidのツイートならば、新着として保存する。

  4. もしも、取得した100件の中に保存したidが含まれていなければ、

    まだまだ新着が埋れている可能性があるのでさらに100件取得。

    保存したidが現れるまで、またはAPI制限の1500件まで、繰返し行う。

【実際のソースコード


CakePHP:コントローラ】
function ajaxGetNewStatus(){
//Ajax処理である
$this->layout = 'ajax';

//JavaScriptから渡された値
$q = $this->params['url']['q']; //検索語
$since_id = $this->params['url']['since_id']; //保存していたid

//最終的に返す新着ステータス配列を定義
$new_status = array();

for($page = 1; $page < 16; $page++){ //上限の1500件÷100=15回繰り返す
$url = "http://search.twitter.com/search.json?rpp=100&q=$q&page=$page";
$status = @file_get_contents($url);

if($status){
//大きすぎる整数値は、デコードする前に文字列として扱うように変換する
// 参考→ http://www.usamimi.info/~oomori/entry/35
$status = preg_replace( '/id":(\d+)/u', 'id":"\1"', $status);
}else{
break; //ツイートを取得できないなら、終了
}
//ここでデコードし、PHPで扱えるようにする
$status = json_decode($status, true);

//$since_idよりも新しいツイートのみを残す
foreach($status['results'] as $val){
if(strval($val['id']) <= strval($since_id)){
//既存ツイートに達したので、終了
$page = 100;
break;
}else{
//新着ツイートだった!
$new_status['results'][] = $val;
}
}
//次回のsince_idを取得
$new_status['max_id'] = (
!isset($new_status['max_id']) &&
isset($status['max_id'])
)
? $status['max_id']
: null;
}
$this->set('status', $new_status);
}