Новичкам в PHP приходится работать с большими наборами данных или массивами. Типичная проблема — страшная ошибка нехватки памяти:
Fatal error: Allowed memory size of xxxxxx bytes exhausted (tried to allocate xxxxx bytes) in your_script.php on line xx
Здесь PHP-скриптом превышен лимит памяти. Чтобы устранить эту ошибку, в PHP 5.5 представили отличное решение — генераторы. Они позволяют перебирать наборы данных, не загружая все в память. Это эффектно и эффективно.
Что такое «генераторы»?
Генераторы — это способ пройтись по набору данных, не создавая полного массива в памяти. То есть на проработку больших наборов данных расходуется меньше памяти.
Принцип работы генераторов
При использовании генератора им не загружается в память весь набор данных, а обрабатывается по одной их части. В PHP это достигается с помощью ключевого слова yield
.
Применение генераторов: пошаговое руководство
1. Базовый синтаксис генератора
Чтобы создать генератор, оператором yield
определяется функция:
function numberGenerator($start = 1, $end = 10) {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
//И для его использования:
foreach (numberGenerator() as $number) {
echo $number . "<br>";
}
2. Преобразование обычной функции в генератор
Рассмотрим функцию, в которой возвращается массив:
function getNumbers($start = 1, $end = 10) {
$numbers = [];
for ($i = $start; $i <= $end; $i++) {
$numbers[] = $i;
}
return $numbers;
}
Использование этой функции с большим значением $end
чревато проблемами с памятью. Преобразуем ее в генератор:
function getNumbersGenerator($start = 1, $end = 10) {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
3. Получение пар «ключ — значение»
С помощью yield
также получаем пары ключ — значение:
function keyValueGenerator() {
yield 'a' => 1;
yield 'b' => 2;
yield 'c' => 3;
}
Обратная отправка данных генераторам
Генераторами данные не только выводятся, с помощью метода send
во время выполнения ими также принимаются входные данные:
function receiveDataGenerator() {
while (true) {
$data = yield;
if ($data === 'stop') {
return; // Выход из генератора
}
echo "Received: $data<br>";
}
}
$generator = receiveDataGenerator();
$generator->send('Hello');
$generator->send('World');
$generator->send('stop');
Возвращение значений из генераторов
Генераторами, используя yield
, не только получают значения, но с помощью return
возвращают конечное значение:
function countdownGenerator($start) {
for ($i = $start; $i >= 0; $i--) {
yield $i;
}
return 'Blastoff!';
}
$gen = countdownGenerator(5);
foreach ($gen as $value) {
echo "$value<br>";
}
echo $gen->getReturn(); // Выводится «'Blastoff!'»
Примеры практического использования
Генераторы особенно полезны в сценариях обработки больших файлов или потоков данных, например при построчном считывании большого файла:
function readFileLineByLine($filename) {
$file = fopen($filename, 'r');
while (!feof($file)) {
yield fgets($file);
}
fclose($file);
}
foreach (readFileLineByLine('large_file.txt') as $line) {
echo $line . "<br>";
}
Генераторы на PHP — это мощный инструмент для управления памятью и обработки больших наборов данных. С ним код пишется чище и эффективнее, отчего значительно облегчается жизнь разработчика.
По мере освоения PHP и включения генераторов в инструментарий, ваши возможности как разработчика, несомненно, расширятся.
Читайте также:
Читайте нас в Telegram, VK и Дзен
Перевод статьи Cleyton Bonamigo: Unlocking the Power of PHP Generators