PHP виконує багато повторюваної роботи на стороні сервера. Один запит може потребувати сканування папки з зображеннями, опитування бази даних до зміни статусу або постійного запиту введення від користувача, доки воно не відповідатиме вашим правилам. Копіювання та вставлення одного й того самого блоку коду для таких завдань зробило б програму крихкою та майже неможливою для підтримки. Цикли існують саме для вирішення цієї проблеми. Вони об'єднують логіку в блок, який можна використовувати повторно, зменшують кількість помилок і роблять ваш застосунок компактнішим.

Більшість PHP-розробників інстинктивно використовують цикл for, коли знають кількість ітерацій, або цикл while, коли кількість залежить від динамічної умови. Проте існує третій варіант, який поводиться достатньо інакше, тому його правильний вибір може значно покращити читабельність коду. Цикл do-while спочатку виконує код у своєму блоці, а потім перевіряє, чи варто запускати його знову.

Чим відрізняється цикл do-while

У стандартному циклі while PHP спочатку перевіряє умову, а вже потім переходить до виконання блоку. Якщо умова спочатку хибна, блок буде повністю пропущено. Цикл do-while змінює цей порядок. Він виконує код один раз, доходить до кінця і лише потім перевіряє умову, щоб вирішити, чи потрібно повертатися на початок.

Синтаксис виглядає так:

do {
    // statements
} while ($condition);

Зверніть увагу на крапку з комою після оператора while. Ця крапка з комою є обов'язковою, і її відсутність призведе до помилки синтаксису. Блок між do та while завжди виконується принаймні один раз, навіть якщо умова є хибною з самого початку. Така поведінка (перевірка після виконання) — це не просто особливість, а головна причина існування цього циклу.

Коли варто використовувати do-while

Є три поширені сценарії, де ця структура є найкращою: відображення меню, валідація введення та повторна спроба виконання завдання, яке може завершитися невдачею. У кожному випадку логіка вимагає, щоб дія відбулася до того, як ви зможете вирішити, чи продовжувати.

Відображення меню

Уявіть інструмент командного рядка або текстову панель адміністратора. Вам потрібно вивести список варіантів, дочекатися вибору користувача, а потім вирішити, чи показувати меню знову. Ви не можете перевірити, чи обрав користувач вихід, доки меню не з'явиться на екрані.

$choice = 0;

do {
    echo "1. View Reports\n";
    echo "2. Export Data\n";
    echo "3. Exit\n";
    
    $choice = (int) readline("Select an option: ");
    
    if ($choice === 1) {
        // fetch and display reports
    } elseif ($choice === 2) {
        // run export logic
    }
} while ($choice !== 3);

Технічно з цим може впоратися і звичайний цикл while, але він змусить вас або повторювати вивід меню перед початком циклу, або ініціалізувати $choice фіктивним значенням лише для того, щоб задовольнити початкову умову. Це розкидає пов'язану логіку по двох місцях. Версія do-while тримає вивід, зчитування та перевірку в одному охайно організованому блоці.

Валідація введення

Валідація введення часто слідує тому самому шаблону. Ви хочете надати користувачеві підказку, перевірити отримані дані та повторити процес, якщо вони не відповідають вашим правилам. Оскільки запит має відбутися до перевірки, цикл do-while підходить сюди ідеально.

do {
    $username = readline("Choose a username (min 3 chars): ");
    $isValid = strlen($username) >= 3;
    
    if (!$isValid) {
        echo "That username is too short.\n";
    }
} while (!$isValid);

Зі стандартним циклом while вам довелося б ініціалізувати $username порожнім рядком і дублювати рядок із запитом перед циклом, щоб умові було що перевіряти. Таке повторення провокує помилки. Якщо пізніше ви зміните текст запиту, ви можете згадати про це всередині циклу, але забути про копію над ним. Структура do-while усуває цей ризик, гарантуючи, що запит виконається всередині блоку до будь-якої перевірки умови.

Повторна спроба невдалого завдання

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

$attempts = 0;
$maxRetries = 3;
$success = false;

do {
    $attempts++;
    $response = @file_get_contents('https://api.example.com/status');
    
    if ($response !== false) {
        $success = true;
    } elseif ($attempts < $maxRetries) {
        sleep(1);
    }
} while (!$success && $attempts < $maxRetries);

if (!$success) {
    // log the permanent failure
}

Важлива деталь полягає в тому, що запит надсилається ще до того, як PHP запитає: «Чи спрацювало це?». Циклу while довелося б виконувати фіктивний запит або встановлювати підробний прапорець успіху перед входом у цикл, що заплутало б реальний процес. Версія do-while робить послідовність прозорою: спроба, перевірка та рішення.

Порівняння do-while та while

Різниця між цими двома циклами полягає в часі виконання. Розглянемо змінну, яка спочатку перебуває у стані, що не пройде жодну перевірку:

$x = 10;

while ($x < 5) {
    echo $x;        // Never runs
}

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

$x = 10;

do {
    echo $x;        // Runs once, outputs 10
} while ($x < 5);

Ця єдина гарантована ітерація є вирішальним фактором. Якщо ваша логіка передбачає нуль або більше ітерацій, while — безпечніший інструмент. Якщо ж логіка вимагає одну або більше ітерацій, do-while зазвичай є чистішим рішенням.

Пастки та найкращі практики

Оскільки цикл do-while гарантує принаймні одне виконання, він також може призвести до нескінченного циклу, якщо не бути обережним. Якщо змінні, що перевіряються в умові, ніколи не змінюються всередині блоку, PHP буде працювати нескінченно або до досягнення максимального часу виконання.

Ще однією поширеною помилкою є пропуск крапки з комою в кінці. Наступний приклад призведе до помилки:

do {
    // code
} while ($x < 5)    // syntax error

Також варто уникати використання do-while за звичкою, коли інший цикл є більш виразним. Якщо ви ітеруєте масив, foreach майже завжди кращий. Якщо ви керуєте простим числовим лічильником, цикл for дозволяє тримати ініціалізацію, умову та інкремент в одному рядку, що легше сприймається при читанні.

З точки зору продуктивності, do-while не створює суттєвих накладних витрат порівняно з while у PHP. Перевага є суто структурною. Коли інший розробник бачить цикл do-while, він одразу розуміє, що блок має виконатися до того, як буде перевірена будь-яка умова. Ця невелика деталь позбавляє його необхідності відстежувати фіктивні змінні або дубльований код налаштування над стандартним циклом while.

Крайні випадки та альтернативні патерни

Іноді цикл do-while є корисним навіть тоді, коли немає взаємодії з користувачем. Наприклад, при роботі з генератором або курсором, який повертає принаймні один елемент, ви можете обробити перший елемент, а потім перевірити, чи перейшов курсор до наступної коректної позиції. У застарілих кодових базах, де використовуються прямі ресурси бази даних замість сучасних наборів результатів, можна зустріти такий патерн:

$row = $result->fetch();
do {
    // process $row
} while ($row = $result->fetch());

Хоча сучасний PHP віддає перевагу foreach з PDO, цей патерн ілюструє, як do-while обробляє першу ітерацію як особливий випадок без додаткових розгалужень.

Головний висновок

Цикл do-while — це вузькоспеціалізований інструмент, але у правильному місці він є єдиним інструментом, який має сенс. Він тримає логіку налаштування та валідації в одному місці, гарантує спробу виконання дії перед її оцінкою та прямо передає ваші наміри наступному розробнику, який читатиме код. Якщо умова має з'явитися після виконання роботи, використовуйте do-while. В усіх інших випадках нехай роботу виконують простіші while, for або foreach.