Reputation: 5877
I have certain use cases where I need to show datasets without pagination. In order to save memory I would rather use Doctrine's batch processing features (the query iterator).
I want to know if twig provides any mechanism (writing my own extension is ok) to allow using the for tag with an iterator result set just as I would with any other collection.
Then in my extension (or whatever handles the iteration process) I would detach the objects as they are used.
So far, I think my only option is creating a custom for tag, as I don't think twig's for tag handles this.
Upvotes: 2
Views: 1282
Reputation: 5877
Considering that:
Instead of passing:
$query->getResult()
to twig you can just pass:
$query->iterate()
Then in twig instead of doing:
{% for item in result %}
{# do work with item #}
{% endfor %}
It should be:
{% for item in result %}
{# doctrine's iterator yields an array for some crazy reason #}
{% set item = item[0] %}
{# do work with item #}
{# the object should be detached here to avoid staying in the cache #}
{% endfor %}
Besides, the loop.last variable stops working, so if you use it you should figure out another way to solve your problem.
Finally, instead of writing a custom twig tag, I just created a Decorator for doctrines iterator to handle the extra stuff that I need, the only still broken is the loop.last var:
class DoctrineIterator implements \Iterator {
public function __construct(\Iterator $iterator, $em) {
$this->iterator = $iterator;
$this->em = $em;
}
function rewind() {
return $this->iterator->rewind();
}
function current() {
$res = $this->iterator->current();
//remove annoying array wrapping the object
if(isset($res[0]))
return $res[0];
else
return null;
}
function key() {
return $this->iterator->key();
}
function next() {
//detach previous entity if present
$res = $this->current();
if(isset($res)) {
$this->em->detach($res);
}
$this->iterator->next();
}
function valid() {
return $this->iterator->valid();
}
}
Upvotes: 5