環境
PHP5.6
Guzzle6.3
公式ドキュメント:
http://docs.guzzlephp.org/en/stable/index.html
guzzle インストール
composerでインストールします。
composer require guzzlehttp/guzzle
簡易版非同期リクエスト
require_once(dirname(__FILE__) . '/vendor/autoload.php');
use GuzzleHttp\Client;
$client = new Client();
//$client = new \GuzzleHttp\Client(['cookies' => true]); //クッキーを利用したい場合
//$client = new \GuzzleHttp\Client(['debug' => true]); //通信内容をデバッグしたい場合
$promises[] = $client->requestAsync('GET', 'https://sample.com/1.html');
$promises[] = $client->requestAsync('GET', 'https://sample.com/2.html');
$promises[] = $client->requestAsync('GET', 'https://sample.com/3.html');
$promises[] = $client->requestAsync('GET', 'https://sample.com/4.html');
$promises[] = $client->requestAsync('GET', 'https://sample.com/5.html');
$responses = \GuzzleHttp\Promise\all($promises)->wait();
$result = [];
foreach ($responses as $response) {
$result[] = [
'html' => $response->getBody()->getContents(),
'status_code' => $response->getStatusCode(), //ステータスコード
'reason_phrase' => $response->getReasonPhrase(), //
'protocol_version' => $response->getProtocolVersion(),
'response_header' => $response->getHeaders()
];
}
var_dump($result);
- 5リクエストを非同期リクエストします
- 非同期なので、$resultに入ってくるレスポンスは順不同
- 非同期でPOSTしたい場合の例は下記です。(フォーム送信したいデータがある・ヘッダ指定したいケース)
$config = [
//ヘッダ指定
'headers' => [
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding' => 'gzip, deflate, br',
'Accept-Language' => 'ja,en-US;q=0.9,en;q=0.8',
'Cache-Control' => 'max-age=0',
'Connection' => 'keep-alive',
'Host' => 'sample.com',
'Upgrade-Insecure-Requests' => 1,
'User-Agent' => 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36'
],
//パラメータ指定
'form_params' => [
'email' => 'test@sample.com',
'name' => 'test'
]
];
$promises[] = $client->requestAsync('POST', 'https://sample.com/aaa.html', $config);
$response = \GuzzleHttp\Promise\all($promises)->wait();
メモリ節約版非同期リクエスト
<?php
require_once(dirname(__FILE__) . '/vendor/autoload.php');
use GuzzleHttp\Pool;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
$client = new Client();
$urlList = [
'https://sample.com/1.html',
'https://sample.com/2.html',
'https://sample.com/3.html',
'https://sample.com/4.html',
'https://sample.com/5.html',
'https://sample.com/6.html',
'https://sample.com/7.html',
'https://sample.com/8.html',
'https://sample.com/9.html',
'https://sample.com/10.html'
];
$requests = function ($urlList) use ($client) {
foreach ($urlList as $url) {
yield function() use ($client, $url) {
return $client->requestAsync('GET', $url);
};
}
};
$contents = [];
$pool = new Pool($client, $requests($urlList), [
'concurrency' => 10,
'fulfilled' => function ($response, $index) use ($urlList, &$contents) {
$contents[$urlList[$index]] = [
'html' => $response->getBody()->getContents(),
'status_code' => $response->getStatusCode(),
'response_header' => $response->getHeaders()
];
},
'rejected' => function ($reason, $index) use ($urlList, &$contents) {
// this is delivered each failed request
$contents[$urlList[$index]] = [
'html' => '',
'reason' => $reason
];
},
]);
$promise = $pool->promise();
$promise->wait();
var_dump($contents);
- 簡易版で大量に非同期リクエストした場合、promiseオブジェクトにリクエスト数分状態を保持してしまうのでメモリオーバーする事がある
- ジェネレータを使うと実際に必要になる(Poolで順次実行される時)までリクエストが実行されずメモリを消費しない
参考:
https://speakerdeck.com/suzuki/guzzle-promisewoshi-tuta-fei-tong-qi-chu-li-niyoruapikorufalsegao-su-hua
https://mike-neko.github.io/blog/guzzle/