Вопросы по PHP: Middle — 8 вопросов с ответами 2026
S.
Sobes AI

Вопросы по PHP на собеседовании: Middle — часть 2/3 с разбором ответов

05.03.2026 | 4 мин чтения | 3 просмотров

Это часть 2 из 3. ← Часть 1: Junior | Часть 3: Senior →

TL;DR: 8 вопросов для Middle PHP-разработчиков — SOLID, copy-on-write, генераторы, OPcache, паттерны, DI, PSR, жизненный цикл запроса. С кодом и разбором ошибок кандидатов. По данным собеседований 2024–2026.

Как пользоваться: Открой перед собеседованием → найди свой уровень → попробуй ответить до чтения разбора → проверь follow-up. Слабые места — в тренажёр.

Это вторая часть серии. Первая — Junior, третья — Senior. Middle-вопросы — это уже не «что такое», а «как работает под капотом» и «почему именно так».

По статистике с easyoffer.ru, SOLID спрашивают у 41% кандидатов на PHP-позиции, а паттерны проектирования — ещё у 35%. Готовься к обоим.

Содержание


1. Объясните принципы SOLID на примерах PHP

SOLID — один из самых частых вопросов для Middle (41% собеседований по данным easyoffer.ru). Интервьюер хочет не определения, а умение применять принципы в реальном коде.

S — Single Responsibility: один класс — одна причина для изменения.

// Плохо: класс и сохраняет, и форматирует отчёт
class Report {
    public function generate(): string { /* ... */ }
    public function saveToFile(string $path): void { /* ... */ }
    public function sendByEmail(string $to): void { /* ... */ }
}

// Хорошо: каждый класс — одна ответственность
class ReportGenerator {
    public function generate(): string { /* ... */ }
}
class ReportSaver {
    public function saveToFile(Report $report, string $path): void { /* ... */ }
}

O — Open/Closed: открыт для расширения, закрыт для модификации.

L — Liskov Substitution: наследник должен работать везде, где работает родитель, без сюрпризов.

I — Interface Segregation: много маленьких интерфейсов лучше одного большого.

// Плохо
interface Worker {
    public function code(): void;
    public function test(): void;
    public function managePeople(): void; // Junior не управляет людьми
}

// Хорошо
interface Coder {
    public function code(): void;
}
interface Tester {
    public function test(): void;
}
interface Manager {
    public function managePeople(): void;
}

D — Dependency Inversion: зависи от абстракций, не от конкретных реализаций.

Типичная ошибка: Кандидат перечисляет расшифровку аббревиатуры, но не может показать нарушение принципа в реальном коде и предложить рефакторинг.

Follow-up: Покажите пример нарушения Liskov Substitution Principle. (Классический пример: Square extends Rectangle, где setWidth() ломает ожидания.)


2. Как работает copy-on-write в PHP?

Показывает глубину понимания внутренностей PHP. По отзывам на Хабре, этот вопрос отличает мидла от джуна — джун обычно не знает.

Copy-on-write (COW) — оптимизация памяти. Когда переменная присваивается другой, PHP не копирует данные сразу. Копирование происходит только при изменении одной из переменных.

$a = str_repeat('x', 1_000_000); // 1MB строка
$b = $a; // НЕ копирует — $b указывает на те же данные
// memory: ~1MB

$b .= 'y'; // ТЕПЕРЬ копирует, потому что $b изменился
// memory: ~2MB

Внутри PHP использует счётчик ссылок refcount в структуре zval. Пока refcount > 1 и данные не изменяются — все переменные ссылаются на одну область памяти.

$array = range(1, 100_000);
$copy = $array;  // refcount = 2, данные общие
// Без COW это бы удвоило потребление памяти

$copy[] = 'new'; // Теперь copy получает свою копию

Это критично для:

  • Передачи больших массивов в функции (по значению — но без COW копирование было бы дорогим)
  • Работы с коллекциями данных
  • Понимания, почему foreach может вести себя неожиданно

Типичная ошибка: Кандидат думает, что передача массива в функцию всегда создаёт копию — на самом деле копия создаётся только при модификации (благодаря COW).

Follow-up: Что произойдёт с COW, если передать переменную по ссылке &? (COW отключается — PHP сразу создаёт отдельный zval с is_ref = true.)


3. Что такое генераторы и зачем нужен yield?

Проверяет, умеет ли кандидат работать с большими объёмами данных, не расходуя всю память. Частый вопрос на Middle по данным разборов PHP-собеседований 2024–2026.

Генератор — функция, которая использует yield вместо return. Она не выполняется целиком, а «отдаёт» значения по одному, приостанавливая выполнение.

// Без генератора — все 1 млн строк в памяти
function readAllLines(string $file): array {
    return file($file); // потребляет ~100MB для большого файла
}

// С генератором — одна строка за раз
function readLines(string $file): Generator {
    $handle = fopen($file, 'r');
    while (($line = fgets($handle)) !== false) {
        yield $line;
    }
    fclose($handle);
}

// Использование
foreach (readLines('huge_file.csv') as $line) {
    processLine($line); // в памяти — одна строка
}

Ключевые особенности:

  • Генератор возвращает объект Generator, который реализует Iterator
  • yield может и отдавать, и принимать значения ($value = yield $result)
  • yield from делегирует выполнение другому генератору
  • Генератор можно итерировать только один раз
// yield from — делегирование
function innerGenerator(): Generator {
    yield 1;
    yield 2;
}

function outerGenerator(): Generator {
    yield 0;
    yield from innerGenerator();
    yield 3;
}

// Результат: 0, 1, 2, 3

Типичная ошибка: Кандидат знает синтаксис yield, но не может объяснить, когда генератор лучше обычного массива и в чём выигрыш по памяти.

Follow-up: Можно ли использовать return внутри генератора? (Да, с PHP 7.0 — значение доступно через $generator->getReturn() после завершения итерации.)


Хорошо, мы разобрали работу PHP под капотом. Дальше — инфраструктурные вопросы: OPcache, паттерны и стандарты.


4. Как работает OPcache и что такое JIT?

Проверяет понимание production-инфраструктуры PHP. Мидл должен понимать, почему PHP быстрый в production и медленный в dev-режиме.

OPcache — встроенное расширение PHP, которое кэширует скомпилированный байткод в разделяемой памяти. Без OPcache PHP при каждом запросе:

  1. Читает .php файл
  2. Лексический анализ → токены
  3. Парсинг → AST (Abstract Syntax Tree)
  4. Компиляция → байткод (opcodes)
  5. Выполнение байткода в Zend VM

С OPcache шаги 1–4 выполняются один раз, дальше байткод берётся из памяти.

JIT (Just-In-Time, PHP 8.0+) — компилирует горячий байткод в машинный код CPU. Добавляет шаг после OPcache:

; php.ini
opcache.enable=1
opcache.jit=1255
opcache.jit_buffer_size=100M

Когда JIT даёт эффект: математика, обработка изображений, ML — CPU-bound задачи. Для типичного веб-приложения (I/O-bound) JIT даёт минимальный прирост, потому что основное время тратится на базу данных и сеть.

Типичная ошибка: Кандидат думает, что JIT ускоряет любое PHP-приложение. На практике для Laravel/Symfony прирост от JIT — 1-5%, основной выигрыш даёт OPcache.

Follow-up: Почему OPcache нужно сбрасывать при деплое? (Потому что закэшированный байткод не обновится при изменении файлов. Решение: opcache_reset() или opcache.validate_timestamps=0 с opcache_reset() в deploy-скрипте.)


5. Назовите основные паттерны проектирования

Паттерны спрашивают у 35% кандидатов на PHP-позиции. Интервьюер хочет не UML-диаграммы, а понимание, когда какой паттерн применять.

Три категории: порождающие, структурные, поведенческие. Для Middle достаточно знать 5–6 ключевых:

Strategy — выбор алгоритма в рантайме:

interface PaymentStrategy {
    public function pay(float $amount): bool;
}

class CreditCardPayment implements PaymentStrategy {
    public function pay(float $amount): bool {
        // логика оплаты картой
        return true;
    }
}

class PayPalPayment implements PaymentStrategy {
    public function pay(float $amount): bool {
        // логика PayPal
        return true;
    }
}

class OrderService {
    public function checkout(Order $order, PaymentStrategy $payment): void {
        $payment->pay($order->getTotal());
    }
}

Factory Method — создание объектов без указания конкретного класса.

Observer — уведомление зависимых объектов об изменениях (Laravel Events — реализация Observer).

Decorator — добавление поведения без изменения класса (Middleware в Laravel — цепочка декораторов).

Repository — абстракция доступа к данным (Eloquent — ActiveRecord, но часто оборачивают в Repository).

Singleton — единственный экземпляр класса. Важно: в PHP Singleton считается антипаттерном, потому что создаёт скрытые зависимости и усложняет тестирование. Лучше использовать DI-контейнер.

Типичная ошибка: Кандидат описывает Singleton как «полезный паттерн» и не знает, почему в PHP-сообществе его считают антипаттерном.

Follow-up: Почему Singleton затрудняет unit-тестирование? (Глобальное состояние — нельзя подменить зависимость моком. DI решает эту проблему.)


6. Что такое Dependency Injection?

DI — один из ключевых архитектурных вопросов для Middle. Все современные PHP-фреймворки построены на DI-контейнерах, по данным обсуждений на Reddit и Хабре за 2024–2026.

Dependency Injection — паттерн, при котором объект получает свои зависимости извне, а не создаёт их сам.

// Плохо — жёсткая связь (tight coupling)
class UserService {
    private MySQLDatabase $db;

    public function __construct() {
        $this->db = new MySQLDatabase(); // создаёт сам
    }
}

// Хорошо — DI через конструктор
class UserService {
    public function __construct(
        private DatabaseInterface $db // получает извне
    ) {}

    public function getUser(int $id): ?User {
        return $this->db->find('users', $id);
    }
}

Три типа DI:

  • Constructor injection — через конструктор (самый распространённый)
  • Method injection — через метод
  • Property injection — через публичное свойство (не рекомендуется)

DI Container (IoC Container) — автоматически разрешает и внедряет зависимости. Laravel Service Container, Symfony DI — примеры.

// Laravel — автоматическое разрешение
class OrderController extends Controller {
    public function __construct(
        private OrderService $orderService, // Laravel сам создаст
        private PaymentGateway $payment     // и это тоже
    ) {}
}

Типичная ошибка: Кандидат путает DI (паттерн) и DI Container (инструмент). DI можно делать руками, без контейнера.

Follow-up: Чем DI отличается от Service Locator? (DI — зависимости приходят извне. Service Locator — объект сам запрашивает зависимости из реестра. DI предпочтительнее, потому что зависимости явные.)


Последние два вопроса — стандарты и протокол. Их задают реже, но знание PSR и понимание жизненного цикла запроса показывают зрелость разработчика.


7. Что такое PSR стандарты?

Проверяет, знает ли кандидат о стандартах PHP-сообщества. По отзывам на Хабре, незнание PSR на Middle-собеседовании — красный флаг для интервьюера.

PSR (PHP Standards Recommendations) — стандарты, разработанные PHP-FIG (Framework Interoperability Group). Ключевые:

PSR-1 / PSR-12 — стиль кода. PascalCase для классов, camelCase для методов, 4 пробела для отступов. PSR-12 расширяет PSR-1 с правилами для PHP 7+.

PSR-4 — автозагрузка классов. Маппинг namespace → директория. Composer реализует PSR-4.

// composer.json
{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

App\Services\PaymentServicesrc/Services/PaymentService.php

PSR-7 — HTTP-сообщения. Стандартные интерфейсы для Request/Response. Используют Slim, Laminas.

PSR-11 — Container Interface. Единый интерфейс для DI-контейнеров.

PSR-3 — Logger Interface. Psr\Log\LoggerInterface — реализуют Monolog, все фреймворки.

Типичная ошибка: Кандидат знает только «PSR — это стандарты кода» и не может назвать конкретные PSR кроме стиля кодирования.

Follow-up: Какой PSR реализует Composer для автозагрузки? (PSR-4. Ранее был PSR-0, но он устарел.)


8. Опишите жизненный цикл HTTP-запроса в PHP

Показывает целостное понимание работы PHP-приложения. Часто задают как заключительный вопрос на Middle по отзывам на Glassdoor.

Классический жизненный цикл (на примере nginx + PHP-FPM):

  1. Клиент отправляет HTTP-запрос
  2. Nginx принимает запрос, определяет, что это PHP, и передаёт в PHP-FPM через FastCGI
  3. PHP-FPM выбирает свободный worker-процесс
  4. Worker загружает скрипт (или берёт байткод из OPcache)
  5. Выполняется index.php → bootstrap фреймворка → routing → controller → response
  6. Ответ возвращается через PHP-FPM → nginx → клиенту
  7. Worker освобождается — PHP очищает память (shared-nothing architecture)

Shared-nothing architecture — ключевая особенность PHP. Каждый запрос начинается с чистого состояния. Нет утечек памяти между запросами (в отличие от Node.js или Go). Это и преимущество (простота, надёжность), и ограничение (нет persistent connections без расширений).

// Типичный index.php в Laravel
require __DIR__.'/../vendor/autoload.php'; // PSR-4
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Kernel::class);
$response = $kernel->handle(
    $request = Request::capture()
);
$response->send();
$kernel->terminate($request, $response);

Типичная ошибка: Кандидат описывает только «запрос приходит, ответ уходит» без понимания роли PHP-FPM, OPcache и shared-nothing архитектуры.

Follow-up: Что такое PHP-FPM и чем он отличается от mod_php? (PHP-FPM — FastCGI Process Manager, отдельный процесс. mod_php — модуль Apache, PHP работает внутри Apache. FPM быстрее и масштабируемее.)


Итого Middle: 8 вопросов. Фокус — SOLID, работа PHP под капотом (COW, OPcache, JIT), паттерны, DI, стандарты. Если можешь объяснить почему, а не только что — ты готов.

Как готовиться

  • SOLID — возьми свой код, найди нарушения. Рефакторинг собственного кода учит лучше любой книги.
  • Внутренности PHP — прочитай серию статей Никиты Попова (nikic) о внутренностях PHP. Это лучший источник.
  • ПаттерныDesignPatternsPHP — документация с примерами на PHP.
  • DI — попробуй написать мини-приложение без фреймворка, с ручным DI. Потом замени на контейнер.

Как попробовать Sobes AI

Sobes AI — ассистент, который помогает на реальных технических собеседованиях в реальном времени.

  1. Зайди на sobesai.app
  2. Скачай и установи приложение
  3. Запусти во время подготовки — задавай вопросы из этой статьи
  4. Sobes AI подскажет, если забудешь разницу между Factory и Strategy
  5. На реальном собесе — работает как невидимый помощник

Это часть 2 из 3. ← Часть 1: Junior | Часть 3: Senior →

Готовитесь к собеседованию?

Sobes AI слушает вопросы интервьюера и генерирует ответы в реальном времени.

Скачать Sobes AI