我知道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);
似乎是错误的,或者是不理想的。这意味着我永远不能发送一个文字null。这是ok的csv写入,但也许有一个用例发送null。
是否有使用php生成器进行顺序写入的"最佳实践"?
不是说这是一个了不起的想法,但如果你谈论语义,这感觉很棒。
检查一个类。比如传入特定类的对象来终止生成器。如:
// 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());
为额外的语义糖添加了一个小工厂
也不理想,但不需要创建任何其他类
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());