Генератор - функція, яка віддає значення по одному через yield і «засинає» між ними. Вона повертає об'єкт Generator, який можна обходити foreach, але значення обчислюються лише тоді, коли їх просять.
function readLines(string $path): Generator
{
$handle = fopen($path, 'r');
try {
while (($line = fgets($handle)) !== false) {
yield $line;
}
} finally {
fclose($handle);
}
}
foreach (readLines('access.log') as $line) {
// у пам'яті лише один рядок, хай файл і 10 ГБ
}
Навіщо:
- Пам'ять. Масив з мільйона рядків займає сотні мегабайтів; генератор - стільки, скільки один елемент.
- Ліниве обчислення. Якщо цикл зупиниться на сотому елементі, решта не обчислюватиметься взагалі.
Обмеження: генератор можна пройти лише один раз, у нього немає count() і довільного доступу за індексом.
У Laravel на генераторах побудовані LazyCollection і cursor() / lazy() в Eloquent.