Skip to content

Instantly share code, notes, and snippets.

@alexeyshockov
Last active December 28, 2020 05:21
Show Gist options
  • Save alexeyshockov/cf20fd85d908ac30e295d0fc4d27be5c to your computer and use it in GitHub Desktop.
Save alexeyshockov/cf20fd85d908ac30e295d0fc4d27be5c to your computer and use it in GitHub Desktop.
<?php
namespace GuzzleDynamicRequests;
require __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
// Do not extend IteratorIterator, because it cashes the return values somehow!
class MapIterator implements \Iterator
{
/**
* @var \Iterator
*/
private $inner;
private $handler;
public function __construct(\Iterator $inner, callable $handler)
{
$this->inner = $inner;
$this->handler = $handler;
}
public function next()
{
$this->inner->next();
}
public function current()
{
return call_user_func($this->handler, $this->inner->current(), $this->inner);
}
public function rewind()
{
$this->inner->rewind();
}
public function key()
{
return $this->inner->key();
}
public function valid()
{
return $this->inner->valid();
}
}
// Do not extend IteratorIterator, because it cashes the return values somehow!
class ExpectingIterator implements \Iterator
{
/**
* @var \Iterator
*/
private $inner;
private $wasValid;
public function __construct(\Iterator $inner)
{
$this->inner = $inner;
}
public function next()
{
if (!$this->wasValid && $this->valid()) {
// Just do nothing, because the inner iterator has became valid.
} else {
$this->inner->next();
}
$this->wasValid = $this->valid();
}
public function current()
{
return $this->inner->current();
}
public function rewind()
{
$this->inner->rewind();
$this->wasValid = $this->valid();
}
public function key()
{
return $this->inner->key();
}
public function valid()
{
return $this->inner->valid();
}
}
// Just for the example, to show the dynamic addition.
$next = new \SplDoublyLinkedList();
$next->push('http://yandex.ru');
$next->push('http://yahoo.com');
$next->push('http://rambler.com');
$next->push('http://bbc.co.uk');
$next->push('http://facebook.com');
$next->push('http://feedly.com');
$httpClient = new Client();
// MapIterator is just better for readability.
$generator = new MapIterator(
// Initial data. This object will be always passed as the second parameter to the callback below
new \ArrayIterator(['http://google.com']),
function ($request, $array) use ($httpClient, $next) {
return $httpClient->requestAsync('GET', $request)
->then(function (Response $response) use ($request, $array, $next) {
// The status code for example.
echo $request . ': ' . $response->getStatusCode() . PHP_EOL;
// New requests.
$array->append($next->shift());
$array->append($next->shift());
});
}
);
// The "magic".
$generator = new ExpectingIterator($generator);
// And the concurrent runner.
$promise = \GuzzleHttp\Promise\each_limit($generator, 5);
$promise->wait();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment