LoginSignup
2

More than 3 years have passed since last update.

Guzzle HTTPでカクテルAPIを叩いてguzzle(酒を暴飲)する

Last updated at Posted at 2019-12-23

エキサイト 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.

Guzzle Documentationより

GuzzleHttpとはPHP HTTPクライアントです。
シンプルなインターフェイスで、POSTリクエストやJSONデータアップロードなど色々なことができます。
また、逐次実行と並行実行どちらも行うことができます。
ちなみに、guzzleとは英語で「(酒)を暴飲する」という意味があるそうです。

ということで!!!!!
今回はGuzzle HTTPでお酒を暴飲(!?):sunglasses::cocktail:しながら説明したいと思います。

『Bar探し と 支度』

Guzzle HTTPでお酒を暴飲するためには、お酒:cocktail:とGuzzle HTTP本体が必要ですね。
用意していきましょう!

HTTPリクエスト先のAPI

カクテルAPI:TheCocktailDB

今回はお酒として、上記のカクテル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で書いてきます。

:sunglasses::point_up:「マスター!おすすめを一杯!」

GETリクエスト

Drink.php
<?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.

:yum:「Manhattan美味しい!」

『酒をいっぱい頼む』

酒を暴飲するのが今回のテーマなので、どんどん飲んでいきましょう。

:hand_splayed::sunglasses:「マスター!おすすめをいっぱいください!」

複数回のGETリクエスト(逐次処理)

SerialDrinks.php

<?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杯飲んでみたいと思います。

:cocktail::cocktail::cocktail::cocktail::cocktail::hand_splayed::sunglasses:「マスター!おすすめを一気にください!!」

複数回のGETリクエスト(並行処理)

ParallelsDrinks.php
<?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を使うのをおすすめします!

:christmas_tree::sunglasses::cocktail:「クリスマス・イブに乾杯!」

参考文献

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2