<? phpukraine СТАТТІ
⌕Пошук по платформі
КАРʼЄРА 29 вересня 2026 · 8 хв читання

Live coding на PHP-співбесіді: як думати вголос і не завмерти

Live coding міряє інше, ніж знання алгоритмів: як ви розбираєте чужу задачу під чужим поглядом і з таймером. Далі три формати, які дають на PHP-позиціях, що питати до першого рядка коду, як озвучувати рішення, щоб інтерв'юер міг вам допомогти, і що робити в ті тридцять секунд, коли в голові порожньо.

РP
Редакція phpukraine
Редакція платформи

Спільна секція з кодом на PHP-співбесіді рідко буває схожою на LeetCode. Найчастіше це шеринг екрана або онлайн-редактор на кшталт CoderPad, від двадцяти до сорока хвилин, задача на п'ятнадцять рядків і людина, яка мовчить і дивиться. Хеш-таблиці тут майже ніколи не бувають причиною провалу. Валить інше: двадцять хвилин людина мовчки пише, стирає, пише знову, і співрозмовник не має жодного шансу зрозуміти, що відбувається.

Нижче про механіку: як влаштовані три типові формати, що говорити і коли, і що робити, коли ви застрягли.

Три формати, і вони перевіряють різне

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

function firstDuplicateSku(array $rows): ?string
{
    $seen = [];

    foreach ($rows as $row) {
        if (isset($seen[$row['sku']])) {
            return $row['sku'];
        }

        $seen[$row['sku']] = true;
    }

    return null;
}

Говорити тут є про що, і саме цього від вас чекають: in_array() всередині циклу дало б квадрат, а масив як хеш-таблиця дає лінійний прохід; isset() поводиться інакше за array_key_exists(), якщо значення може бути null, і тут це безпечно тільки тому, що я кладу true. Одне речення про кожну з цих двох речей коштує більше, ніж ще одна написана функція.

Рефакторинг. Дають метод на 40-60 рядків і просять привести до ладу. Дивляться на два вміння: чи ви міняєте код, не змінюючи поведінку, і чи помічаєте те, що лежить прямо в коді.

public function price(Order $order): float
{
    $total = 0;
    foreach ($order->items as $item) {
        if ($item->type == 'digital') {
            $total += $item->price;
        } else {
            if ($item->weight > 1000) {
                $total += $item->price + 50;
            } else {
                $total += $item->price + 20;
            }
        }
    }
    if ($order->user->isVip == true) {
        $total = $total - ($total * 10 / 100);
    }
    return $total;
}

Половина роботи тут не в коді, а в питаннях. Ціна у float означає, що знижка 10% на 1999.99 дасть хвіст у сімнадцятому знаку; перехід на цілі копійки це зміна контракту, і її треба узгодити, а не зробити тихцем. weight > 1000 це магічне число без одиниці виміру. Порівняння == true зайве, а == замість === на рядку з типом це готовий баг, коли type раптом прийде як 0.

Сам рефакторинг після цього виходить скромний: match замість вкладених if, винесена доставка окремим методом, ранній вихід для порожнього замовлення. Не поспішайте розбивати клас на п'ять нових. За двадцять хвилин це виглядає не як архітектура, а як недописаний код.

Мініфіча. «Напиши сервіс, який не дає слати той самий лист частіше ніж раз на годину.» Тут цікавлять межі: де у вас логіка, де залежності, чи можна це протестувати без Redis і без бази.

final readonly class Throttle
{
    public function __construct(
        private Clock $clock,
        private AttemptStore $store,
        private int $intervalSeconds = 3600,
    ) {}

    public function allow(string $key): bool
    {
        $last = $this->store->lastAttemptAt($key);
        $now = $this->clock->now();

        if ($last !== null && $now->getTimestamp() - $last->getTimestamp() < $this->intervalSeconds) {
            return false;
        }

        $this->store->remember($key, $now);

        return true;
    }
}

Тільки завдяки годиннику через інтерфейс, а не new DateTimeImmutable() всередині, цю штуку взагалі можна протестувати без sleep(3600). Скажіть це вголос одразу, коли пишете конструктор, бо саме на цьому місці інтерв'юер ставить собі галочку.

Питання до першого рядка коду

Умову формулюють коротко навмисно. Три-чотири питання перед кодом читаються як досвід, а не як тупцювання.

Що питати по суті: скільки елементів на вході і чи вони вміщаються в пам'ять, чи є вхід відсортованим, що робити з некоректним рядком (кинути виняток, пропустити, повернути null), чи важливий порядок результату, чи можна міняти вхідний масив. Для мініфічі додайте питання про сховище: чи дозволено вважати, що є якийсь Store, чи писати все в пам'яті.

Окремо запитайте про версію PHP у пісочниці. Онлайн-редактори часто стоять на 8.1 або 8.2, і array_find() з array_any(), які з'явилися у 8.4, там просто не існують. Те саме з json_validate() з 8.3. Втратити три хвилини на Call to undefined function в середині задачі неприємно.

Останнє: домовтеся, що пишете. «Я зроблю чисту функцію без фреймворку, Laravel-обгортку не чіпаю, згода?» Це економить обом десять хвилин.

Що саме говорити вголос

Думати вголос не означає коментувати натискання клавіш. «Зараз я пишу foreach» не несе інформації. Корисна репліка звучить інакше.

Назвіть підхід одним реченням до того, як почнете: «Пройду один раз, складу мапу sku в кількість, потім відфільтрую ті, де більше одиниці. Лінійно за часом, лінійно за пам'яттю.» Тепер співрозмовник знає ваш план і може зупинити, якщо він хибний, поки ви не витратили на нього десять хвилин.

Проговорюйте те, що свідомо відкладаєте: «Валідацію вхідних даних поки пропускаю, вважаю, що масив уже нормалізований, повернуся, якщо буде час.» Різниця між «не подумав» і «відклав свідомо» видно тільки з ваших слів.

Називайте розвилки, а не тільки рішення. «Тут можна usort з компаратором або array_multisort. Беру usort, бо компаратор читабельніший, і з PHP 8.0 сортування стабільне, тож однакові ключі не переставляться.» Це якраз той рівень, за яким відрізняють людину з практикою від людини, що вивчила синтаксис.

Мовчати теж можна. Тридцять секунд тиші нормальні, якщо ви їх позначили: «Дай хвилину, я подумаю над межами циклу.» Мовчанка стає проблемою, коли вона незрозуміла.

Найбільше шкодить інше: виправдовування. «Вибач, я зазвичай так не пишу», «я хвилююся», «давно не писав без IDE» повторені тричі перетворюють технічну розмову на розмову про ваш стан. Один раз сказати «без автодоповнення можу переплутати порядок аргументів у array_filter» достатньо, це чесно і нікого не бентежить.

Тести пишуться раніше, ніж закінчено код

У пісочниці рідко є PHPUnit чи Pest, тому найшвидша перевірка це таблиця кейсів і printf унизу файлу.

$cases = [
    'порожній вхід'  => [[], null],
    'без дублікатів' => [[['sku' => 'A'], ['sku' => 'B']], null],
    'дублікат'       => [[['sku' => 'A'], ['sku' => 'B'], ['sku' => 'A']], 'A'],
    'sku як число'   => [[['sku' => '0'], ['sku' => '0']], '0'],
];

foreach ($cases as $name => [$rows, $expected]) {
    $actual = firstDuplicateSku($rows);
    printf("%-15s %s\n", $name, $actual === $expected ? 'ok' : 'FAIL: '.var_export($actual, true));
}

Останній кейс тут не випадковий. '0' як ключ масиву стане цілим 0, і будь-яка перевірка через if ($seen[$sku]) замість isset() тихо зламається. Якщо ви самі принесли такий кейс і показали, що він проходить, це сильніший сигнал, ніж правильна відповідь на пряме питання.

Список меж, який варто тримати в голові для PHP-задач: порожній масив і масив з одного елемента; null, 0, '' і '0' там, де код покладається на truthiness; від'ємні числа; гроші у float; рядки з кирилицею, де strlen() дасть байти, а треба mb_strlen(); дати на межі місяця і різні таймзони; ключі-числа в асоціативних масивах.

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

Коли застрягли

Найгірший сценарій: тиша, стирання написаного і повернення до тієї самої точки втретє. Виходів кілька, і кожен кращий за мовчазну паніку.

Зробіть наївно і скажіть про це: «Пишу рішення в лоб, квадратичне, головне щоб працювало. Далі прискорю, якщо залишиться час.» Робочий брутфорс з правильними тестами майже завжди зараховують. Порожній екран не зараховують.

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

Відріжте шматок, який заважає. Напишіть виклик $normalized = $this->normalize($row); і поставте нижче заглушку. Задача стає меншою, а інтерв'юер бачить декомпозицію.

Питайте точково. «Я не знаю» закриває розмову, а «я вагаюся між мапою і сортуванням, розмір входу має значення?» відкриває. Підказку дадуть майже завжди, і взята підказка коштує дешевше, ніж двадцять хвилин у глухому куті. Якщо ви пішли не туди, скажіть про це прямо і поверніться: «Цей шлях ускладнюється, відкочуся до варіанта з мапою.»

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

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

ПИШЕТЕ ПРО PHP?Опублікуйте розбір або історію з проєкту на платформіРедактор із чеклістом, редактура, авторська сторінка. Републікація з блогу отримує canonical на оригінал. Відкрити редактор →
РP
Редакція phpukraine
Редакція платформи
Матеріали, які готує команда платформи на основі власних даних: каталогу вакансій, зарплатного звіту й банку питань. Кожна цифра в них рахується з бази, а не береться з голови.
оновлено 3 жовтня 2026 · ліцензія CC-BY-SA-4.0
ДАЛІ ПО ТЕМІ
ЧИТАТИ ДАЛІ
← Усі статті