2016-11-02 18 views
3

データイテレータを作成するためにyieldを使用することができます。 CSVファイルからデータを読み込みます。"データ出力ストリーム"のために/ yield:Generator :: send()を使用する

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を送ることはできません。どちらがCSV書き込みにはいいですか?おそらく、nullを送るためのユースケースがあります。

逐次書き込みにPHPジェネレータを使用するための「ベストプラクティス」はありますか?

+0

これはジェネレータの問題ではありません。あなたはファイルの終わりに達した後に1回チェックする必要がある 'while(!feof($ handle))'を持っています。それは同じ問題です。 – apokryfos

+0

さて、ここではセマンティクスについて話しています。あなたは 'true'、' false'、 'null'なども送ることができます。それはあなたの呼び出しです。あなたは 'ヌル'と公正なポイントを作る。私は駄目だ、私は冗長な文字列のようなものを送るだろうと思うが、なぜか私はシステムを設計していないのだから恐ろしい考えだ。 – Andrew

+0

@apokryfosしかし、feof()は別の関数であるため、fgetcsv()の可能な戻り値の範囲を制限しません。もちろん、これはcsvでは無意味です。なぜなら、fgetcsv()がnullを返すと、それはEOFだからです。入力イテレータはすでに - > valid()と - > current()のために別々のメソッドで設計されているので、 - > current()はEOFを意味することなくnullを返すことができます。しかし、出力/書き込み用ではありません。 – donquixote

答えて

1

これは素晴らしいアイデアですが、あなたがセマンティクスを話しているなら、これは素晴らしいと感じます。

クラスを確認してください。ジェネレータを終了するために特定のクラスのオブジェクトを渡すようにします。 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()); 

余分なセマンティックシュガーについては、ここに小さな工場を追加しました。

+0

はい、これは動作し、リテラルNULLを送信できるようになります。私はこれが本当に全体的に改善しているかどうかはわかりませんが、それは私が言っている有効な答えです。 – donquixote

関連する問題