I know that yield can be used to create a data iterator, e.g. to read data from a CSV file.
function csv_generator($file) {    
  $handle = fopen($file,"r");
  while (!feof($handle)) {
    yield fgetcsv($file);
  }
  fclose($file);
}
But the Generator::send() method suggests that I can do the same for sequential writing, instead of reading.
E.g. I want to use the thing like this:
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);
The above will work, I think.
But $output_generator->send(null); for closing seems wrong, or not ideal. It means that I can never send a literal null. Which is ok for csv writing, but maybe there is a use case for sending null.
Is there any "best practice" for using php generators for sequential writing?
Not saying this is a marvelous idea but if you're talking semantics, this 'feels' great.
Check against a class. Like pass in objects of a particular class to terminate the generator. Like:
// 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());
Added a little factory in here for extra semantic sugar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With