PHP'de Generator Kullanımı

Generator PHP 5.5.0 ile gelmiş olan önemli bir yenilik olup, en basit ve net tanımı, memory'den(hafızadan) kazanım sağlayabileceğiniz iteratörler olduğudur. Açıkçası generator'ın önemini ben de başta pek idrak edememiştim, ancak daha sonradan çok büyük dosyalar üzerinde işlem yaparken, karşılaştığım memory problemleri, generator kullanmanın ne kadar önemli olduğunu bana acı bir şekilde öğretmişti.

Burada da verilen en klişe, ama net olan örneği vereceğim.
foreach (range(0, 1000000) as $number) {
    echo $number;
}
Üstteki örnekte, 1'den 1000000'a kadar olan tüm numaraları yazdırıyorsunuz. PHP bu range'i(aralığı) oluştururken, 1'den 1000000'a kadar olan tüm rakamları, bir dizi içerisinde, memory'de oluşturup, tüm rakamların yer aldığı bir array(dizi) olarak geri döndürüyor. Kısacası, foreach ile range arasındaki iletişim sadece bir kere oluyor ve döngü bitene kadar, bir milyon tane integer için, memory'de yer tutuluyor. Eğer aynı şeyi, herhangi bir zamanda, memory'de sadece bir integer tutacak şekilde gerçeklemek isterseniz, generator kullanmanız lazım.
function myRange($length) {
    for($i = 0; $i < $length; $i++) {
        yield $i;
    }
}

foreach (myRange(1000000) as $number) {
    echo $number;
}
Eğer üstteki gibi bu örneği gerçeklerseniz, memory'de 1 milyon tane integer için yer işgal etmektense, foreach ile myRange fonksiyonu arasındaki iletişim döngü bitene kadar devam edeceği için, döngünün herhangi bir zamanında, sadece bir integer'ın yer kapladığı şekilde memory'i kullanacaksınız. Bunu sağlayan kısım da yield oluyor. yield'ın biraz daha kafanızda şekillenmesi için açıklayacak olursam, yield'ı, return gibi düşünebilirsiniz, ama aralarındaki en temel fark, return ile fonksiyon çalışmayı durdurup(stop) değerleri döndürürüken, yield ile fonksiyon çalışmasına ara verir(pause) ve çağrıldığı yer için bir değer sağlar.

Bu örnek sizin için gerçek hayat senaryosu gibi gelmemiş olabilir. Ancak düşünün ki 10 milyon satırdan oluşan bir text dosyasını okumanız lazım. Eğer dosyanın tamamını, memory'de tutup, satırları memory'den okumaya çalışırsanız, yani her bir satırı dizi içerisine atıp, sonrasında da bu diziyi döndürürseniz, mükemmel bir sunucunuz yoksa, memory'nin yetersiz olduğu konusunda hata alırsınız. Ancak her bir satırı okurken, yield kullanırsanız, herhangi bir şekilde hafıza problemiyle karşılaşmazsınız, o yüzden dosyadan satırları okurken, alttaki gibi bir yaklaşım daha iyi olacaktır.
function file_lines($filename) {
    $file = fopen($filename, 'r');
    while (($line = fgets($file)) !== false) {
        yield $line;
    }
    fclose($file);
}

foreach (file_lines('dosya.txt') as $line) {
    // yapmak istediginiz islemler
}
Kısacası, ne zaman ki büyük bir dosya ya da grup ile ilgili işlem yapmanız gerekirse, memory'nizi gereksiz yere işgal etmemek için, aklınıza gelen ilk kullanım, generatorlar olmalıdır.