Я знаю, что 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, но, возможно, есть вариант использования для отправки нулевого значения.
Есть ли «лучшие практики» для использования 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());
Здесь добавлена небольшая фабрика для дополнительного семантического сахара.
Других решений пока нет …