前言
本文為《現代 PHP》一書的學習筆記。
環境
產生器
產生器(Generator)在需要的時刻計算並產生運算後的數値,避免占用寶貴的記憶體空間。
產生器的例子如下:
1 2 3 4 5 6 7 8 9
| function myGenerator() { yield 'value1'; yield 'value2'; yield 'value3'; }
foreach (myGenerator() as $value) { echo $value . PHP_EOL; }
|
範例 2-16:Range 產生器(不良示範)
1 2 3 4 5 6 7 8 9 10 11 12 13
| function makeRange($length) { $dataset = []; for ($i = 0; $i < $length; $i++) { $dataset[] = $i; }
return $dataset; }
$customRange = makeRange(1000000); foreach ($customRange as $i) { echo $i . PHP_EOL; }
|
- 此範例宣告了一個
$dataset 陣列並配置了一百萬個整數的記憶體空間。
範例 2-17:Range 產生器(良好示範)
1 2 3 4 5 6 7 8 9
| function makeRange($length) { for ($i = 0; $i < $length; $i++) { yield $i; } }
foreach (makeRange(1000000) as $i) { echo $i . PHP_EOL; }
|
產生器只是一個使用數次 yield 關鍵字的 PHP 函式,沒有回傳値。
假如需要疊代一個 4 GB 的逗號分隔値(CSV),但是虛擬私人主機只有 1 GB 的可用記憶體,此時將需要使用到產生器。
範例 2-18:CSV 產生器
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function getRows($file) { $handle = fopen($file, 'rb'); if (!$handle) { throw new Exception(); } while (!feof($handle)) { yield fgetcsv($handle); } fclose($handle); }
foreach (getRows('data.csv') as $row) { print_r($row); }
|
fopen() 函數用來打開一個文件。
feof() 函數用來檢測是否已到達文件末尾。
fgetcsv() 函數用來解析 CSV 字段。
fclose() 函數用來關閉一個文件。
產生器是只能往前的疊代器,無法用來倒帶、快轉或搜尋資料群集。
參考資料
- Josh Lockhart(2015)。現代 PHP。台北市:碁峯資訊。