Jira issue originally created by user arnaud-lb:
Instead of returning queried objects, Query::iterate returns arrays with the queried objects as single elements, like mixed results :
$query = $em->createQuery('SELECT f FROM \Foo');
foreach($query->iterate() as $row) {
print_r($row); // $row is an array(0 => \Foo instance)
}
Comment created by @beberlei:
This is documented behaviour, not a bug
http://www.doctrine-project.org/projects/orm/2.0/docs/reference/batch-processing/batch-processing#iterating-large-results-for-data-processing
Comment created by arnaud-lb:
I originally checked the ::iterate() method documentation, but did not found anything about that.
Thanks!
Issue was closed with resolution "Fixed"
Hi,
This is indeed documented (here now: Iterating Large Results for Data-Processing )
But is there any valid reason for that behaviour? I mean, it's a non-sense, as there can be only one result when iterating, and everyone would expect the foreach loop to produce the objects, not an array with one object.
What am i missing?
In my case, that prevented me to use an export bundle, which expects an iterator to produce CSV, because it's not made to dig one level deep into the results it gather from the iterator...
Suggestion: add a iterateSimple() method which does what is expected.
@amorel-ljsl workaround of this nasty behaviour is PHP7 yield.
/**
* @return Entity[]
*/
public function findAllHuge()
{
$iterator = $this->createQueryBuilder('e')
->getQuery()
->iterate();
foreach ($iterator as $row) {
yield $row[0];
}
}
Great tip @garex , thank you!
@Ocramius Can we do something about this? Like another method that would work as expected? (See this comment)
Not in 2.x but feel free to propose/submit improvement for 3.0.
For those who can't use PHP "yield" (wich is available from PHP 5.5), you still can create a decorator :
class IterableResultDecorator implements \Iterator
{
protected $iterableResult;
public function __construct(IterableResult $iterableResult)
{
$this->iterableResult = $iterableResult;
}
public function current()
{
$current = $this->iterableResult->current();
return null !== $current ? $current[0] : null;
}
public function next()
{
$this->iterableResult->next();
}
public function key()
{
return $this->iterableResult->key();
}
public function valid()
{
return $this->iterableResult->valid();
}
public function rewind()
{
$this->iterableResult->rewind();
}
}
Then you can do something like :
$results = new IterableResultDecorator($qb->getQuery()->iterate());
foreach ($results as $result) {
// ...
}
Please do upgrade to a newer PHP version: older releases are no longer production-ready and should be considered a business and security risk.
Most helpful comment
Hi,
This is indeed documented (here now: Iterating Large Results for Data-Processing )
But is there any valid reason for that behaviour? I mean, it's a non-sense, as there can be only one result when iterating, and everyone would expect the foreach loop to produce the objects, not an array with one object.
What am i missing?
In my case, that prevented me to use an export bundle, which expects an iterator to produce CSV, because it's not made to dig one level deep into the results it gather from the iterator...
Suggestion: add a
iterateSimple()method which does what is expected.