APIをGETでコールして配列を取得したい

ちょっとしたプロジェクトで、他社サービスのAPIを利用する必要があったのでメモ。PHPからAPIをGETでコールして戻ってくるJSONデータ(文字列)をPHP用に配列にパースして戻す処理を書きたかったので書いた。

/**
 * GET Request send.
 *
 * @param  string $url
 * @param  array  $params
 * @return array|boolean $data
 */
public function getJson( $url, $params = array() ) {
	if ( count( $params ) > 0 ) {
		$query = '?' . http_build_query( $params );
	} else {
		$query = '';
	}
	$url .= $query;

	$response = get_headers( $url );

	if ( preg_match( '/(200)/', $response[0] ) ) {
		$headers = array(
			'Content-type: application/json; charset=UTF-8',
			'Accept: application/json'
		);

		$options = array( 'http' => array(
			'method' => 'GET',
			'header' => implode( '\r\n', $headers )
		));

		$data = file_get_contents( $url, false, stream_context_create( $options ) );

		if ( $data !== false ) {
			$data = json_decode( $data );
		}
	} else {
		$data = false;
	};
	return $data;
}

処理の流れは以下の通り。

  1. 9 – 13行目:引数の$paramsがセットされてくればhttp_build_query関数でクエリ文字列を生成
  2. 14行目:クエリ文字列をURLに結合
  3. 16行目:get_headers関数でAPI先のヘッダー情報を取得
  4. 18行目:ヘッダー情報からレスポンスコード200(正常)を判断
  5. 19 – 22行目:セットするヘッダー情報を配列に保存
  6. 24 – 27行目:ストリームコンテキスト用のオプション情報を配列に保存
  7. 29行目:file_get_contents関数でコンテンツを取得
  8. 31 – 33行目:正常に取得できたらjson_decode関数でJSON文字列形式を配列に変換

この関数をClass化して(getRequestという名前にします)、インスタンスを生成して動かしてみます。試しに、このサイトのWP REST APIを使用して、カテゴリー番号「1」のデータを1件コールしてみます。

$response = new getRequest();
$params   = array(
	"per_page"   => 1,
	"categories" => 1
);
$response->getJson( "https://www.terakoya.work/wp-json/wp/v2/posts", $params );

とれた!\(^o^)/
これでAPIに接続してデータの取得をしよう。

重いぞ……file_get_contents

先程1件取得する処理は対して時間がかからなかったのですが、10件取ろうと思ったら重い……6秒ぐらいかかる。そこで、cURL(カール)を使用して同じ処理を書いてみました。

/**
 * GET Request send.(cURL)
 *
 * @param  string $url
 * @param  array  $params
 * @return array|boolean $data
 */
public function curlJson( $url, $params = array() ) {
	if ( count( $params ) > 0 ) {
		$query = '?' . http_build_query( $params );
	} else {
		$query = '';
	}
	$url .= $query;

	$headers = array(
		'Content-type: application/json; charset=UTF-8',
		'Accept: application/json'
	);

	if ( !function_exists( 'curl_version' ) ) {
		return false;
	}

	$ch = curl_init();

	curl_setopt( $ch, CURLOPT_URL, $url );
	curl_setopt( $ch, CURLOPT_TIMEOUT, 60 );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
	$data = curl_exec( $ch );

	$response = curl_getinfo( $ch, CURLINFO_HTTP_CODE );

	curl_close( $ch );

	if ( $response === 200 ) {
		$data = json_decode( $data );
	} else {
		$data = false;
	};

	return $data;
}

処理の流れは以下の通り。

  1. 9 – 13行目:引数の$paramsがセットされてくればhttp_build_query関数でクエリ文字列を生成
  2. 14行目:クエリ文字列をURLに結合
  3. 16 – 19行目:セットするヘッダー情報を配列に保存

ここまではfile_get_contentsでの処理と同じ。ここからcURL(カール)の出番。

  1. 21 – 23行目:curl_version関数の存在チェックをしてcURLがインストールされているか確認
  2. 25行目:curl-init関数でcURLのセッションを初期化
  3. 27 – 30行目:curl_setopt関数でcURL転送用オプションを設定
  4. 31行目:curl_exec関数でセッションを実行
  5. 33行目:curl_getinfo関数に引数でCURLINFO_HTTP_CODEを渡しレスポンスコードを取得
  6. 35行目:curl_close関数でcURLのセッションを閉じる
  7. 37 – 41行目:レスポンスコード200(正常)が返ってきたらjson_decode関数でJSON文字列形式を配列に変換

これを同じようにクラス内に定義してコールしてみます。

$response = new getRequest();
$params   = array(
	"per_page"   => 1,
	"categories" => 1
);
$response->curlJson( "https://www.terakoya.work/wp-json/wp/v2/posts", $params );

取れた!\(^o^)/(速い!)
うおお、6秒が1秒になった速い。しかし、file_get_contentsを使うにしても、cURLを使うにしてもその環境で使えるかどうかの判断処理は入れる必要があるな。