我想提供一些数据。问题是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;
}
}
答案 0 :(得分: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()
方法作为生成器。您可能无法做到这一点,但通常是可以做到的,而且并不困难或费时。
答案 1 :(得分:-1)
尝试这一点,它应该更像你的第一次尝试,同时实际上产生一些明智的东西:
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()以便使用chunk的内存效率:
public function workRowData(\closure $rowDataWorker)
{
$this->transactionQuery
->getQuery()
->chunk(5, $rowDataWorker);
}
$rowDataWorker
可以绑定到应该包含某些最终结果的变量,或者可以使用$this
来访问实例变量。