← Назад к вопросам
Что такое генераторы в PHP и как работает оператор yield?
2.0 Middle🔥 111 комментариев
#PHP Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Генераторы в PHP и Оператор yield
Генераторы — это специальные функции в PHP, которые позволяют создавать итеративные последовательности данных без необходимости загружать все данные в памяти сразу. Оператор yield превращает обычную функцию в генератор, возвращая значения по одному.
Основная идея
// ❌ Без генератора — загружает всё в память
function getNumbers($count) {
$numbers = [];
for ($i = 0; $i < $count; $i++) {
$numbers[] = $i;
}
return $numbers; // Большой массив в памяти!
}
$nums = getNumbers(1000000); // Создаёт массив из 1 млн элементов
foreach ($nums as $num) {
echo $num;
}
// ✅ С генератором — ленивое вычисление
function getNumbers($count) {
for ($i = 0; $i < $count; $i++) {
yield $i; // Возвращает по одному значению
}
}
// Память минимальна, значения генерируются по мере итерации
foreach (getNumbers(1000000) as $num) {
echo $num;
}
Как работает yield
function generateSequence() {
yield 1; // Первая итерация вернёт 1
yield 2; // Вторая итерация вернёт 2
yield 3; // Третья итерация вернёт 3
}
foreach (generateSequence() as $value) {
echo $value; // Выведет: 1 2 3
}
// Эквивалент (без генератора):
// return [1, 2, 3];
yield с ключами
// ✅ Можно указывать ключи
function getUsersFromDB() {
yield 1 => ["name" => "Alice", "email" => "alice@example.com"];
yield 2 => ["name" => "Bob", "email" => "bob@example.com"];
yield 3 => ["name" => "Charlie", "email" => "charlie@example.com"];
}
foreach (getUsersFromDB() as $id => $user) {
echo "$id: {$user["name"]}\n";
}
// Более практично — из БД
function fetchUsersFromDB(PDO $pdo) {
$stmt = $pdo->query("SELECT * FROM users");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
yield $row["id"] => $row;
}
}
foreach (fetchUsersFromDB($pdo) as $id => $user) {
// Обрабатываем пользователя (памяти занимает только одна строка!)
processUser($user);
}
yield from для делегирования
function generator1() {
yield 1;
yield 2;
}
function generator2() {
yield 3;
yield 4;
}
// ❌ Долгий путь
function combined1() {
foreach (generator1() as $value) {
yield $value;
}
foreach (generator2() as $value) {
yield $value;
}
}
// ✅ Короче с yield from
function combined2() {
yield from generator1();
yield from generator2();
}
foreach (combined2() as $num) {
echo $num; // 1 2 3 4
}
Двусторонняя коммуникация с send()
function echoGenerator() {
$received = yield "Hello";
echo "Received: $received\n";
$received = yield "World";
echo "Received: $received\n";
}
$gen = echoGenerator();
echo $gen->current(); // Hello
$gen->send("foo"); // Печатает: Received: foo
echo $gen->current(); // World
$gen->send("bar"); // Печатает: Received: bar
Практические примеры
Чтение больших файлов:
// ✅ Потоковое чтение файла
function readLargeFile($filepath) {
$handle = fopen($filepath, "r");
while (!feof($handle)) {
yield fgets($handle);
}
fclose($handle);
}
foreach (readLargeFile("/tmp/huge.csv") as $line) {
processLine($line);
// Всегда в памяти только одна строка!
}
Пагинация на лету:
function paginate($items, $pageSize = 10) {
$offset = 0;
while ($offset < count($items)) {
yield array_slice($items, $offset, $pageSize);
$offset += $pageSize;
}
}
foreach (paginate($bigList, 50) as $page) {
echo "Processing page\n";
foreach ($page as $item) {
// Обрабатываем по 50 элементов за раз
}
}
Фильтрация данных:
function filterNumbers($numbers, $minValue) {
foreach ($numbers as $num) {
if ($num >= $minValue) {
yield $num;
}
}
}
$allNumbers = range(1, 1000000);
foreach (filterNumbers($allNumbers, 500000) as $num) {
echo $num;
}
Преимущества генераторов
- Экономия памяти — не загружает всё в массив
- Ленивые вычисления — вычисляет только нужное
- Потоковая обработка — идеально для больших данных
- Чистота кода — красивая итерация
- Производительность — быстрее, чем большие массивы
Когда использовать
- Чтение больших файлов
- Работа с большими наборами данных из БД
- API, возвращающие потоки данных
- Финансовые калькуляции с большим числом операций
- Обработка логов в реальном времени