Розглядаємо PHP генератори

5 хв. читання

PHP генератори - корисне поняття, щоб зрозуміти світ розробки PHP.

Коли справа доходить до керування автомобілем, швидкість – це не все, що необхідно. Але в вебі, швидкість означає дещо інше. Чим швидший ваш додаток, тим кращий досвід користувача. Ця стаття присвячена PHP генераторам, але чому ми говоримо про швидкість? Скоро ви зрозумієте, генератори мають великий вплив на швидкість і управління пам'яттю.

Що таке PHP генератори?

Додані в PHP в версії 5.5, генератори є функціями, які забезпечують простий спосіб для перебору даних без необхідності створення масиву в пам'яті. Ще трохи плутаєтесь? Приклад – хороший спосіб показати генератори в дії.

По-перше, швидко створимо файл generator.php який ми будемо використовувати в цьому керівництві. Після створення файлу, ми додамо цей невеликий фрагмент коду.


function getRange ($max = 10) {
    $array = [];

    for ($i = 1; $i < $max; $i++) {
        $array[] = $i;
    }

    return $array;
}

foreach (getRange(15) as $range) {
    echo "Dataset {$range} <br>";
}

Ми можемо швидко розпакувати вбудований PHP-сервер в каталог, де ми створили файл generator.php:

php -S localhost:8000

Тому якщо ми перейдемо за адресою (http://localhost:8000/generator.php), ми отримаємо щось на зразок наступного:

Розглядаємо PHP генератори

Код скаже все сам за себе, і його, безумовно, не так багато. Але якщо ми повернемося в наш код і зробимо невеликі зміни, то матимемо:

foreach (getRange(PHP_INT_MAX) as $range) {
    echo "Dataset {$range} <br>";
}

Тепер upper range(max) зі згенерованих чисел - PHP_INT_MAX, що є найбільшим числом, якого може досягти ваша версія PHP. Після цього, зайдіть у браузер і оновіть його. Але на цей раз ви побачите щось інше. Генератор видасть помилку.

Розглядаємо PHP генератори

Відбулося переповнення пам'яті. Можливі рішення, які приходять на розум: звернутись в php.ini і збільшити memory_limit. Задамо собі питання, чи дійсно це буде ефективно? Чи хочемо ми мати один скрипт, який міститиме всю пам'ять нашого сервера? Відповіді – ні та ні. Це не ефективно, і ми не хочемо скрипт, який використовуватиме всю нашу пам'ять.

Використання генераторів

Визначимо ту ж функцію, яку використовували вище, викличемо її з тим же значенням PHP_INT_MAX і запустимо програму знову. Але, на цей раз, ми будемо створювати функцію-генератор.


function getRange ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        yield $i;
    }
}

foreach (getRange(PHP_INT_MAX) as $range) {
    echo "Dataset {$range} <br>";
}

Розглядаючи функцію getRange, ми тільки виконуємо цикл за значеннями й даємо вихідну інформацію - yield. yield схожий на return, оскільки він повертає значення з функції, але з тією лише різницею, що yield повертає значення тільки тоді, коли це необхідно, і не намагається зберегти весь набір даних в пам'яті.

Якщо ви зайдете у свій браузер, ви повинні побачити дані, які відображаються на сторінці.

Примітка: Генератори можуть бути використані тільки у функції.

Навіщо потрібні генератори?

Є моменти, коли ми хотіли б розібрати великий набір даних (це можуть бути лог-файли), виконувати обчислення на великих базах даних і т.д. Але ми не хочемо викривлювати всю пам'ять. Ми повинні намагатися зберегти пам'ять якомога довше. Дані не обов'язково повинні бути великими - генератори є ефективними незалежно від того, наскільки маленький набір даних. Не забувайте, що наша мета полягає в збільшенні швидкості при використанні меншої кількості пам'яті.

Значення, що повертаються

Є моменти, коли наші дані мають сенс тільки тоді, коли вони є ключовими. При використанні генераторів, ми можемо повертати значення, наприклад:

function getRange ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        $value = $i * mt_rand();

        yield $i => $value;
    }
}

Потім ми можемо піти далі і використовувати пари значень, оскільки ми могли б зробити це з будь-яким масивом, наприклад:

foreach (getRange(PHP_INT_MAX) as $range => $value) {
    echo "Dataset {$range} has {$value} value<br>";
}

Надсилання змінних до генераторів

Генератори можуть також приймати змінні. Це означає, що генератори дозволяють вводити значення в них, це може бути команда або щось інше. Наприклад, ми можемо послати змінну до нашого генератора, щоб зупинити виконання або змінити output. За допомогою функції getRange, яка вже була наведена вище, ми можемо зробити це:

function getRange ($max = 10) {
    for ($i = 1; $i < $max; $i++) {
        $injected = yield $i;

        if ($injected === 'stop') return;
    }
}

Щоб надіслати значення, зробіть наступне:

$generator = getRange(PHP_INT_MAX);

foreach ($generator as $range) {
    if ($range === 10000) {
        $generator->send('stop');
    }

    echo "Dataset {$range} <br>";
}

Примітка: Використання return в генераторі порушить функцію генератора.

Не зловживайте генераторами

Використання PHP_INT_MAX трохи недоречне. Для мене PHP_INT_MAX це 2147483647, а саме:

два мільярди сто сорок сім мільйонів чотириста вісімдесят три тисячі шістсот сорок сім

Генератори повинні бути ефективними. Це не означає, що вони не будуть викликати ту ж проблему, яку вони намагаються вирішити при неправильному використанні.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 4.8K
Приєднався: 10 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація