エキサイト Advent Calendar 2019 24日目の記事です!
こんにちは!aharenchです!
今回は、PHPのHTTP Clientの「GuzzleHttp」について書きたいと思います。
Guzzle HTTPとは
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services.
・ Simple interface for building query strings, POST requests, streaming large uploads, streaming large downloads, using HTTP cookies, uploading JSON data, etc...
・ Can send both synchronous and asynchronous requests using the same interface.
GuzzleHttpとはPHP HTTPクライアントです。
シンプルなインターフェイスで、POSTリクエストやJSONデータアップロードなど色々なことができます。
また、逐次実行と並行実行どちらも行うことができます。
ちなみに、guzzleとは英語で「(酒)を暴飲する」という意味があるそうです。
ということで!!!!!
今回は**Guzzle HTTPでお酒を暴飲(!?)**しながら説明したいと思います。
『Bar探し と 支度』
Guzzle HTTPでお酒を暴飲するためには、お酒とGuzzle HTTP本体が必要ですね。
用意していきましょう!
HTTPリクエスト先のAPI
今回はお酒として、上記のカクテルAPIを利用します。
このAPIでは、カクテルの材料やグラス、作り方の情報を取得することができます。
以下のURIで、idを条件にカクテルの詳細情報を取得できます。
https://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=11000
どうやらこのidは1番開始では無いらしく、11000番代からカクテルの情報があるようです。
インストール
GuzzleHttpのインストールは、Composerを利用して行います。
# 1.プロジェクト作成
$ mkdir Bar && cd $_
# 2.composer インストール
$ curl -sS https://getcomposer.org/installer | php
# 3.guzzlehttpをインストール
$ php composer.phar require guzzlehttp/guzzle:~6.0
『酒を1杯頼む』
準備ができたので、さっそくカクテルAPIにGETリクエストを送ってみましょう!
今回は、素のPHPで書いてきます。
「マスター!おすすめを一杯!」
GETリクエスト
<?php
require "vendor/autoload.php";
use GuzzleHttp\Client;
$client = new Client([
// クライアントのBaseURI
'base_uri' => 'https://www.thecocktaildb.com',
]);
// 次のURIにリクエストを送る -> 'https://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=11000'
$response = $client->request('GET', "api/json/v1/1/lookup.php?i=11000");
// データ整形
$json = json_decode($response->getBody(), true);
$drinks = $json['drinks'];
// 結果出力
foreach ($drinks as $drink) {
print_r("I drank {$drink['strDrink']}.");
}
実行結果
I drank Manhattan.
「Manhattan美味しい!」
『酒をいっぱい頼む』
酒を暴飲するのが今回のテーマなので、どんどん飲んでいきましょう。
「マスター!おすすめをいっぱいください!」
複数回のGETリクエスト(逐次処理)
<?php
require "vendor/autoload.php";
use GuzzleHttp\Client;
$client = new Client([
'base_uri' => 'https://www.thecocktaildb.com',
]);
// 計測開始
$timeStart = microtime(true);
$total = 10;
$drinkList = [];
for ($i = 0; $i < $total; $i++) {
// GETリクエスト 逐次実行
$id = 11000 + $i;
$response = $client->request('GET', "api/json/v1/1/lookup.php?i={$id}");
// データ整形
$json = json_decode($response->getBody(), true);
$drinks = $json['drinks'];
foreach ($drinks as $drink) {
$drinkList[] = $drink['strDrink'];
}
}
// 結果出力
foreach ($drinkList as $drink) {
print_r("I drank {$drink}.\n");
}
// 計測終了
$time = microtime(true) - $timeStart;
print_r("実行時間:{$time} 秒");
I drank Mojito.
I drank Old Fashioned.
I drank Long Island Tea.
I drank Negroni.
I drank Whiskey Sour.
I drank Dry Martini.
I drank Daiquiri.
I drank Margarita.
I drank Manhattan.
I drank Moscow Mule.
実行時間:4.882071018219 秒
お酒を1杯ずつ味わって飲むのもいいですが、10杯飲むのに約4秒かかってしまいました。
これでは、1時間に約9000杯しか飲めません。
これじゃ暴飲とは言えません。
なんと、GuzzleHttpは並行処理が可能です。
とりあえず、今回は1度に5杯飲んでみたいと思います。
「マスター!おすすめを一気にください!!」
複数回のGETリクエスト(並行処理)
<?php
require "vendor/autoload.php";
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
$client = new Client([
'base_uri' => 'https://www.thecocktaildb.com',
]);
// 計測開始
$time_start = microtime(true);
// リクエスト処理定義
$requests = function ($total) {
for ($i = 0; $i < $total; $i++) {
$id = 11000 + $i;
yield new Request('GET', "api/json/v1/1/lookup.php?i={$id}");
}
};
// promiseオブジェクトを生成
$drinkList = [];
$pool = new Pool($client, $requests(10), [
//並行数
'concurrency' => 5,
// リクエストが成功した場合の処理
'fulfilled' => function (Response $response) use (&$drinkList) {
$json = json_decode($response->getBody(), true);
$drinks = $json['drinks'];
foreach ($drinks as $drink) {
$drinkList[] = $drink['strDrink'];
}
},
// リクエストが失敗した場合の処理
'rejected' => function (RequestException $reason) {
print_r("例外:" . $reason->getMessage() . "\n");
},
]);
// promiseオブジェクトを並行処理で実行
$promise = $pool->promise();
// 実行したリクエストの処理を待つ
$promise->wait();
// 結果出力
foreach ($drinkList as $drink) {
print_r("I drank {$drink}.\n");
}
// 計測終了
$time = microtime(true) - $time_start;
echo "実行時間:{$time} 秒";
実行結果
I drank Whiskey Sour.
I drank Mojito.
I drank Old Fashioned.
I drank Long Island Tea.
I drank Negroni.
I drank Margarita.
I drank Manhattan.
I drank Dry Martini.
I drank Daiquiri.
I drank Moscow Mule.
実行時間:1.3625779151917
約1秒で10杯飲むことができました。
これで1時間に約36000杯飲むことができます。
大分、酒を暴飲できたのではないでしょうか。
まとめ
GuzzleHttpのGETリクエストの逐次処理と並行処理を紹介しました。
並行処理をしたことで4倍のスピードを出すことができました。
今回は説明しませんでしたが、
冒頭で説明したようにシンプルにHTTPリクエストを行えるので
外部APIを利用する際はGuzzleHttpを使うのをおすすめします!
「クリスマス・イブに乾杯!」