Skip to content

Instantly share code, notes, and snippets.

@predakanga
Created August 21, 2018 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save predakanga/8159bd5ab9774dbbd7db151cb593feb6 to your computer and use it in GitHub Desktop.
Save predakanga/8159bd5ab9774dbbd7db151cb593feb6 to your computer and use it in GitHub Desktop.
{% for key, val in data %}
Key: {{ key }}
Value: {{ val ?: "0" }}
{% endfor %}
<?php
require_once('vendor/autoload.php');
$twig = new Twig_Environment(new Twig_Loader_Filesystem('.'), ['debug' => true]);
class LazyContext implements ArrayAccess, IteratorAggregate
{
private $storage = [];
private $generator;
public function __construct(Generator $generator)
{
$this->generator = $generator;
}
private function waitForMore()
{
// NB: The try-finally construct is weird, but necessary for the fastest speeds!
// We want to yield before advancing the generator, to avoid waiting for the next item
// However, this means that if waitForMore is terminated early, it never advances
// This causes the last key to be emitted twice
// The sane but less-speedy way is to move the yield after the next, drop the try-finally
try {
// Foreach resets the generator on each call to waitForMore, so we'll iterate by hand
while ($this->generator->valid()) {
$key = $this->generator->key();
$value = $this->generator->current();
$this->storage[$key] = $value;
yield $key;
$this->generator->next();
}
} finally {
if ($this->generator->valid()) {
$this->generator->next();
}
}
}
public function offsetGet($offset)
{
if (array_key_exists($offset, $this->storage)) {
return $this->storage[$offset];
}
foreach ($this->waitForMore() as $key) {
if ($key === $offset) {
return $this->storage[$offset];
}
}
throw new OutOfBoundsException("Key {$offset} is not set");
}
public function offsetExists($offset)
{
if (array_key_exists($offset, $this->storage)) {
return true;
}
foreach ($this->waitForMore() as $key) {
if ($key === $offset) {
return true;
}
}
return false;
}
public function offsetSet($offset, $value)
{
throw new LogicException('Context is read-only');
}
public function offsetUnset($offset)
{
throw new LogicException('Context is read-only');
}
public function getIterator()
{
foreach ($this->storage as $key => $value) {
yield $key => $value;
}
foreach ($this->waitForMore() as $key) {
yield $key => $this->storage[$key];
}
}
}
function controllerFunc()
{
yield 'template' => 'index.twig';
foreach (range('a', 'z') as $key) {
$shouldWait = (bool)random_int(0, 1);
if ($shouldWait) {
sleep(random_int(1, 3));
}
yield $key => $shouldWait;
}
}
$ctx = new LazyContext(controllerFunc());
echo "Template is: {$ctx['template']}\n";
$twig->display($ctx['template'], ['data' => $ctx]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment