使用php yield / Generator :: send()获取“数据输出流”

时间:2016-11-02 14:59:44

标签: php php-generators

我知道yield可用于创建数据迭代器,例如从CSV文件中读取数据。

function csv_generator($file) {    
  $handle = fopen($file,"r");
  while (!feof($handle)) {
    yield fgetcsv($file);
  }
  fclose($file);
}

但是Generator :: send()方法表明我可以为顺序写入做同样的事情,而不是阅读。

E.g。我想用这样的东西:

function csv_output_generator($file) {
  $handle = fopen('file.csv', 'w');
  while (null !== $row = yield) {
    fputcsv($handle, $row);
  }
  fclose($handle);
}

$output_generator = csv_output_generator($file);
$output_generator->send($rows[0]);
$output_generator->send($rows[1]);
$output_generator->send($rows[2]);
// Close the output generator.
$output_generator->send(null);

我认为上述情况会奏效。

$output_generator->send(null);关闭似乎是错误的,或者不理想。这意味着我永远不会发送文字null。这对于csv编写是可以的,但也许有一个用例来发送null。

使用php生成器进行顺序编写是否有“最佳实践”?

2 个答案:

答案 0 :(得分:1)

不是说这是一个了不起的想法,但如果你说的是语义,那么这就是“感觉”。大。

检查班级。像传递特定类的对象来终止生成器一样。像:

objMyCmd.CommandText = "IF (Select object_id('TempDB..#Step1')) IS NOT NULL" & _
" Begin " & _
"   Drop Table #Step1 " & _
" End " & _
 " SELECT a.[RDT_FileID],a.[Master Policy Number], a.[Work item /Submission no#],a.[Insured Name], a.[Credited Office], " & _
                                " a.[Credited Underwriter], a.[Product Line], a.[Product Line Subtype], a.[Current Status], a.[Effective Date], a.[Expiry Date],  a.[Premium in USD $] " & _
                                " INTO #Step1 " &_
                                " FROM  dbo.View_Property_Rater_Of_Record a " & _
                                " WHERE a.[Master Policy Number] Is Not Null " & _
                                " AND a.[RDT_FileID] is null " & _
                                " AND a.[Product Line Subtype] <>  '0102-Marine' " & _
                                " AND a.[Effective Date] >= '2014-04-01' " & _
                                " SELECT * from #Step1 WHERE [Current Status] ='Bound' "

在这里添加了一个小工厂,以获得额外的语义糖。

答案 1 :(得分:0)

也不理想,但无需创建任何其他类即可工作

function csv_output_generator($file) {
  $handle = fopen($file, 'w');
  try {
    while ($row = yield) {
      fputcsv($handle, $row);
    }
  } catch (ClosedGeneratorException $e) {
    // closing generator
  }

  fclose($handle);
}

$output_generator = csv_output_generator($file);
$output_generator->send($rows[0]);
$output_generator->send($rows[1]);
$output_generator->send($rows[2]);
// Close the output generator.
$output_generator->throw(new ClosedGeneratorException());