5

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

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

但是 Generator::send() 方法表明我可以对顺序写入执行相同的操作,而不是读取。

例如,我想使用这样的东西:

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);对于关闭似乎是错误的,或者不理想。这意味着我永远不能发送文字空值。这对于 csv 写入是可以的,但也许有一个发送 null 的用例。

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

4

2 回答 2

1

不是说这是一个了不起的想法,但如果你在谈论语义,这“感觉”很棒。

检查一个类。就像传入特定类的对象以终止生成器一样。喜欢:

// should probably use namespacing here.
class GeneratorUtilClose {}

class GeneratorUtil {
    public static function close() {
        return new GeneratorUtilClose;
    }
}

function csv_output_generator($file) {
  $handle = fopen('file.csv', 'w');

  while (!(($row = yield) instanceof GeneratorUtilClose)) {
    fputcsv($handle, $row);
  }

  fclose($handle);
}

$output_generator = csv_output_generator($file);
$output_generator->send($rows[0]);
$output_generator->send(GeneratorUtil::close());

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

于 2016-12-22T16:10:10.700 回答
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());
于 2019-07-04T15:37:24.300 回答