1. 程式人生 > 其它 >php中 yield生成器的簡單使用

php中 yield生成器的簡單使用

原因: 為了防止php變數太大(比如sql出查詢10w條資料放入陣列)導致記憶體溢位。

 

傳統解決方法: 記憶體溢位時報 **Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)** 錯誤,以往通過php.ini或者ini_set() 來設定一個程序的更大記憶體,雖然能解決大記憶體問題但不利於介面的效能。

 

yield原理:假如有100條資料 用foreach就是一次性把資料放到一個數組,記憶體長度佔100。 用yield是一條一條放進去,而且每次放完一條就“銷燬”,然後總記憶體是一條,記憶體長度只佔1

可以想象yield有點類似 return

 

 

常見使用場景

用法1,處理一個返回值或一個鍵值對

// 傳統
function
createRange($number){ $data = []; for($i=1;$i<$number;$i++){ $data[$i] = time(); } return $data; }
// yield
function
createRange($number){ for($i=1;$i<$number;$i++){ yield $i => time(); } }
$result = createRange(10); // 這裡返回生成器物件(裡面是我們要的陣列data,但記憶體只佔1) foreach($result as $k=>$value){echo $value.$k; }

 

 

用法2,處理sql查詢出來的陣列

public static function yieldData($data){
    foreach ($data as $datum){
        yield $datum;
    }
}

$res = Db()->select();
$list = self::yieldData($res);

// 邏輯處理
foreach($list as $k => &$v){} // 匯出等等 Common::csv($list)

 

用法3,檔案讀取/匯入功能

function readTxt($path)
{
    $handle = fopen($path, 'rb');
    while (feof($handle)===false) {
        yield fgets($handle);
    }
    fclose($handle);
}

foreach (readTxt() as $key => $value) {
   // 邏輯處理
}

 

總結

yield生成器允許你 在 foreach 程式碼塊中寫程式碼來迭代一組資料,而不需要在記憶體中建立一個數組,極大提高了程序的記憶體使用率

 

其它細節可參考:https://segmentfault.com/a/1190000012334856