4

我想提供一些数据。问题是该chunk方法需要关闭才能完成这项工作。在这种情况下,有没有办法从foreach循环中产生数据?

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)
            }
        });
}

我试过这个,但它只会返回最后的结果:

public function yieldRowData(): \Iterator
{
    $results = [];

    $this->transactionQuery
        ->getQuery()
        ->chunk(5, function(Collection $transactions) use (&$results) {
            $results = $transactions;
        });

    foreach($results as $transactionEntity) {
        yield $transactionEntity;
    }
}
4

2 回答 2

0

您没有明确提到chunk()方法(或其他)是否从闭包内返回产生的数据;但我想不会。

如果它返回(即它是一个生成器函数),那么yield from是最好的选择:

// We are inside the method
yield from $query->chunk(5, function ($collection) {
    foreach ($collection as $element) {
        yield $element->getId();
    }
});

但是,如果它不是生成器功能,那么您必须使用其他解决方案。正如其他人所提到的,您可能不想将结果保存在变量中并返回它,因为它会浪费内存(尤其是在大数据量上)。

但是还有另一种可能有效的解决方案。如果幸运的话,其中的代码chunk()不会很复杂,因此您可以从它的类扩展并将chunk()方法重写为生成器。您可能无法做到这一点,但通常这是可能的,而且并不难或耗时。

于 2019-07-11T08:42:43.450 回答
-2

试试这个,它应该更接近你的第一次尝试,同时实际产生一些明智的东西:

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;
    }
}

在下面的注释中添加替代想法:将闭包传递给 yieldRowData() 以使用块的内存效率:

public function workRowData(\closure $rowDataWorker)
{
    $this->transactionQuery
        ->getQuery()
        ->chunk(5, $rowDataWorker);
}

$rowDataWorker可以绑定到一个应该包含一些最终结果的变量,或者可以$this用来访问实例变量。

于 2018-03-07T14:55:39.460 回答