Help us understand the problem. What is going on with this article?

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

エキサイト 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:「クリスマス・イブに乾杯!」

参考文献

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした