I would like to yield some data. Problem is that chunk
method require closure which do the job. Is there way to yield data like from foreach
loop in this situation?
public function yieldRowData(): \Iterator
{
$this->transactionQuery
->getQuery()
->chunk(5, function ($collection) { // This is executed for each 5 elements from database
foreach ($collection as $element) {
yield $element->getId(); // I want this to be yield from this method (yieldRowData)
}
});
}
I tried this, but it will return only last results:
public function yieldRowData(): \Iterator
{
$results = [];
$this->transactionQuery
->getQuery()
->chunk(5, function(Collection $transactions) use (&$results) {
$results = $transactions;
});
foreach($results as $transactionEntity) {
yield $transactionEntity;
}
}
Try this it should resemble your first try more closely while actually yielding something sensible:
public function yieldRowData(): \Iterator
{
$results = [];
$this->transactionQuery
->getQuery()
->chunk(5, function(Collection $collection) use (&$results) {
foreach ($collection as $element) {
$results[] = $element->getId();
}
});
foreach($results as $transactionEntity) {
yield $transactionEntity;
}
}
Adding alternative idea as to the comment below: Pass in the closure to yieldRowData() in order to use the memory efficiency of chunk:
public function workRowData(\closure $rowDataWorker)
{
$this->transactionQuery
->getQuery()
->chunk(5, $rowDataWorker);
}
$rowDataWorker
could be bound to a variable that should contain some end result or can use $this
to access instance variables.
You didn't mention explicitly whether chunk()
method (or whatever) returns the yielded data from within the closure or not; but I guess it won't.
If it returns (i.e. it's a generator function), then yield from
is the best choice:
// We are inside the method
yield from $query->chunk(5, function ($collection) {
foreach ($collection as $element) {
yield $element->getId();
}
});
However, if it is not a generator function, then you have to use other solutions. Probably, as others mentioned, you don't want to save the results inside a variable and return it, as it wastes memory (especially on large data sizes).
But there is another solution that may work. If you are lucky, the code in chunk()
won't be complicated, so you can extend from its class and rewrite the chunk()
method as a generator. You may not be able to do that, but usually it is possible and not really hard or time-consuming.