Генераторы (yield) в PHP: экономим память на больших файлах
Автор:
Eugeny Nosenko
Дата публикации:
2025-09-15 11:25:30 144
Работа с большими объёмами данных — частая задача разработчика. Стандартный подход — загружать весь файл в память, но это может привести к исчерпанию ресурсов и замедлению работы скрипта. К счастью, в PHP есть инструмент, который позволяет обрабатывать данные поэтапно, без перегрузки памяти — генераторы.
Что такое генераторы
Генераторы — это особый тип функций в PHP, которые возвращают данные не сразу все, а по одному элементу. Это похоже на «ленивую» итерацию: вы запрашиваете следующий элемент только тогда, когда он нужен.
Для создания генератора используется ключевое слово yield.
Пример простого генератора:
function numbers() {
for ($i = 1; $i <= 3; $i++) {
yield $i;
}
}
foreach (numbers() as $num) {
echo $num . PHP_EOL;
}
Скрипт выведет:
1 2 3
В отличие от обычного массива, здесь не создаётся полный список чисел в памяти.
Пример: читаем большой CSV по строкам
Допустим, у нас есть файл data.csv размером в несколько гигабайт. Если использовать file() или fgetcsv() в цикле, можно столкнуться с проблемой памяти. Генераторы позволяют «стримить» строки:
function readCsv(string $filename): Generator
{
$handle = fopen($filename, 'r');
if ($handle === false) {
throw new RuntimeException("Не удалось открыть файл $filename");
}
try {
while (($row = fgetcsv($handle)) !== false) {
yield $row;
}
} finally {
fclose($handle);
}
}
// Использование
foreach (readCsv('data.csv') as $row) {
// Обрабатываем каждую строку
print_r($row);
}
Что происходит:
- Файл открывается и читается построчно
- Каждая строка возвращается через
yieldкак элемент генератора - Память не заполняется целиком — в каждый момент в памяти только одна строка
Преимущества подхода
- ⚡️ Экономия памяти — не загружаем весь файл целиком
- 🚀 Скорость — обрабатываем данные по мере поступления
- 🧩 Простота — код читается как обычный foreach
Вывод
Генераторы — отличный инструмент для работы с большими объёмами данных в PHP. Они позволяют обрабатывать файлы по частям, избегая проблем с памятью и ускоряя работу скриптов.
Если вы до сих пор читали большие файлы целиком — попробуйте yield. Результат вас приятно удивит.