Guzzle で Twitter REST API を叩く


PHPのTwitter API関連のライブラリとしては有名どころでは、[twitteroauth](https://github.com/abraham/twitteroauth)や[hybridauth](https://github.com/hybridauth/hybridauth)、[opauth](https://github.com/opauth/opauth)などがありますが、PHPの古いオブジェクト指向な実装だったり、過剰に分厚い実装（※1）だったりして、場合によってはプロジェクトに組み込みにくい場合があります。

今回、PHPのHTTP通信周りのライブラリとしてデファクトになりつつある[guzzle](https://github.com/guzzle/guzzle)に、[oauth-subscriber](https://github.com/guzzle/oauth-subscriber)（※2）というちょうど良いプラグインがあることを知り、これで薄い実装を書いてみました。

※1　認証処理とAPIを叩く処理が密に結合していてたり、バッチ（コマンドライン）から使えそうになかったり
※2 [oauth-subscriber](https://github.com/guzzle/oauth-subscriber)は現状、OAuth1.0aにしか対応していません(2014年9月末時点)が、OAuth2.0に対応するための[議論/実装](https://github.com/guzzle/oauth-subscriber/issues/1)も進められており、近々対応版がリリースされそうです。

# ソース

## composer.json

```php
	"require": {
		"guzzlehttp/guzzle": "~4.0",
		"guzzlehttp/oauth-subscriber": "~0.1"
	},
```

## 実装

とりあえず```GET```してみる

```php
<?php

namespace TwitterRestApiClient;

use GuzzleHttp\Client;
use GuzzleHttp\Message\ResponseInterface;
use GuzzleHttp\Subscriber\Oauth\Oauth1;

class TwitterRestApiClient
{
	/**
	 * @var Client
	 */
	private $client;

	/**
	 * @param string $consumerKey      consumer key
	 * @param string $consumerSecret   consumer secret
	 * @param string|null $token       token
	 * @param string|null $tokenSecret token secret
	 */
	public function __construct($consumerKey, $consumerSecret,
								$token = null, $tokenSecret = null)
	{
		$client = new Client([
			"base_url" => "https://api.twitter.com/1.1/",
			'defaults' => ['auth' => 'oauth']
		]);

		$oauth1 = null;
		if (isset($token) && isset($tokenSecret)) {
			$oauth1 = new Oauth1([
				"consumer_key"    => $consumerKey,
				"consumer_secret" => $consumerSecret,
				"token"           => $token,
				"token_secret"    => $tokenSecret,
			]);
		} else if (!isset($token) && !isset($tokenSecret)) {
			$oauth1 = new Oauth1([
				"consumer_key"    => $consumerKey,
				"consumer_secret" => $consumerSecret,
			]);
		} else {
			throw new \InvalidArgumentException("token or tokenSecret is empty.");
		}

		$client->getEmitter()->attach($oauth1);

		$this->client = $client;
	}

	/**
	 * GET Resource
	 *
	 * @param string $resource
	 * @param array  $params
	 * @return object
	 */
	public function get($resource, $params = [])
	{
		$queryString = "";
		if (count($params) > 0) {
			$queryString = "?" . http_build_query($params);
		}

		/** @var ResponseInterface $response */
		$response = $this->client->get($resource . ".json" . $queryString);
	
		// 連想配列として結果を取得
		return $response->json();

		// 結果を Object(stdClass) として取得したい場合
		// return $response->json(["object" => true]);
	}
}
```

# 使い方

## ソース

```php
<?php

use TwitterRestApiClient;

$consumerKey    = "CONSUMER_KEY";
$consumerSecret = "CONSUMER_SECRET";
$token          = "TOKEN";
$tokenSecret    = "TOKEN_SECRET";

$client = new TwitterRestApiClient($consumerKey, $consumerSecret, $token, $tokenSecret);

$params = [
	"q"           => "#qiita",
	"lang"        => "ja",
	"locale"      => "ja",
	"result_type" => "recent",
	"count"       => 10,
];

$result = $client->get("search/tweets", $params);

var_dump($result);
```

## 結果

レスポンスの内容についてはAPIドキュメント（[GET search/tweets](https://dev.twitter.com/rest/reference/get/search/tweets)）を参照。

```php
array(2) {
  'statuses' =>
  array(10) {
    [0] =>
    array(25) {
      'metadata' =>
      array(2) {
        'iso_language_code' =>
        string(2) "ja"
        'result_type' =>
        string(6) "recent"
      }
      'created_at' =>
      string(30) "Sun Sep 21 15:18:05 +0000 2014"
      'id' =>
      int(513708751056941056)
      'id_str' =>
      string(18) "513708751056941056"
      'text' =>
      string(148) "RT @hatebu: PHP - スクリプトインジェクション入門 - Qiita (65 users) http://t.co/fNpdCNWEYs 3件のコメント http://t.co/7UHHBmLyyy"

    :
    :

  }
  'search_metadata' =>
  array(9) {
    'completed_in' =>
    double(0.008)
    'max_id' =>
    int(513708751056941056)
    'max_id_str' =>
    string(18) "513708751056941056"
    'next_results' =>
    string(88) "?max_id=513708751056941055&q=qiita&lang=ja&count=1&include_entities=1&result_type=recent"
    'query' =>
    string(5) "qiita"
    'refresh_url' =>
    string(82) "?since_id=513708751056941056&q=qiita&lang=ja&result_type=recent&include_entities=1"
    'count' =>
    int(1)
    'since_id' =>
    int(0)
    'since_id_str' =>
    string(1) "0"
  }
}
```