Библиотека собеса по PHP | вопросы с собеседований
3.16K subscribers
191 photos
6 videos
126 links
Вопросы с собеседований по PHP и ответы на них.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/9f3affba

Для обратной связи: @proglibrary_feeedback_bot
Download Telegram
Что такое атрибуты в PHP 8 и как они используются?

Атрибуты (аннотации) — это новый механизм, который позволяет добавлять метаданные к классам, методам, свойствам и функциям. Это аналог аннотаций в других языках (например, в Java), но с улучшенной интеграцией в сам язык PHP.

💡 Что такое атрибуты?

Атрибуты — это специальные декларации, которые позволяют прикреплять дополнительную информацию к элементам кода. Они выглядят как комментарии, но их можно обрабатывать программно. Например:

#[Route(«/home»)]class HomeController { //...}


🛠 Как это работает?

🔹 Синтаксис атрибутов

Атрибуты начинаются с символа # и квадратных скобок []. Это позволяет избежать путаницы с обычными комментариями. Пример:
#[ExampleAttribute(«value»)]class MyClass { //...}


🔹 Доступ к атрибутам

Атрибуты могут быть прочитаны через Reflection API, что позволяет вам работать с метаданными программно. Пример:
$reflection = new ReflectionClass(MyClass::class);$attributes = $reflection->getAttributes();


🔹 Использование в фреймворках

Атрибуты идеально подходят для фреймворков, которые требуют метаданных для маршрутизации, валидации и других операций. Например, в Symfony они могут использоваться для описания маршрутов, а в Laravel — для валидации.

Преимущества атрибутов

Явность: метаданные непосредственно в коде, легко видны.
Простота использования: код становится более читаемым и лаконичным.
Гибкость: легко обрабатывать с помощью Reflection и других инструментов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1👏1
За год мы провели три потока курса по ИИ-агентам, а теперь запускаем масштабное обновление!

В новом, четвёртом потоке мы учли все пожелания студентов, добавили большой блок про AgentOps и сместили фокус с базовых концепций на суровый инжиниринг. Рассказать про SOLID и особенности PHP 8 на собеседовании легко, а вот сделать автономного агента, который не сливает бюджет проекта на токены — задача со звёздочкой.

В программе:

— практика с первого занятия: Jupyter-ноутбуки с автопроверкой;
— оркестрация в LangGraph: human-in-the-loop и механизм time-travel;
— продвинутый RAG для продакшена и парсинг сложных документов;
— контроль экономики агентов: маршрутизация и кеширование запросов;
— развёртывание локальных опенсорс-моделей с соблюдением 152-ФЗ.

В честь старта продаж действует спецпредложение: 3 курса по цене 1 (два дополнительных курса в подарок).

Доступ к материалам для предварительной подготовки откроется сразу после оплаты.

По промокоду Agent забирайте скидку 10 000 ₽ (89 000 ₽ вместо 99 000 ₽). Успейте занять место до 28 февраля!

👉 Присоединиться к четвёртому потоку и вывести агентов в прод
Что такое позднее статическое связывание (Late Static Binding) и зачем оно нужно?

LSB — механизм, который позволяет в статическом контексте ссылаться на реально вызванный класс, а не на тот, в котором написан метод.

Проблема: self:: всегда указывает на класс, где метод определён:
php
class Base {
public static function create() {
return new self(); // всегда вернёт Base!
}
}

class Child extends Base {}

Child::create(); // вернёт Base, а не Child


С static:: PHP смотрит на класс, через который был сделан вызов:
phpclass Base {
public static function create() {
return new static(); // вернёт тот класс, который вызвал
}
}

class Child extends Base {}

Child::create(); // вернёт Child
Please open Telegram to view this post
VIEW IN TELEGRAM
👍52🔥2🥱2
💬 Обратная связь

Проверим, сколько среди нас джедаев синьоров. Ваш примерный грейд:

🔥 — Senior
👍🏼 — Middle
❤️ — Junior
😁 — Ещё учусь
Please open Telegram to view this post
VIEW IN TELEGRAM
👍36🔥2711😁8👾1
Последний шанс: 3 курса по цене 1 и запуск AI-агентов в продакшн

На собеседованиях по PHP всё чаще проверяют умение работать с внешними ИИ-сервисами. Как обогатить бэкенд мультиагентными системами, контролировать затраты на API и работать по 152-ФЗ?

Обновлённая программа делает упор на жёсткий инжиниринг и вывод в прод. Вы научитесь строить ReAct-циклы, работать с LangGraph и AutoGen, внедрять продвинутый RAG, протоколы MCP и AgentOps. Все ключевые навыки в одном месте: измеримость систем, time-travel дебаггинг, управление браузером, human-in-the-loop и развёртывание в закрытых контурах.

Почему нельзя откладывать:

— масштабная акция «3 курса по цене 1» сгорает уже сегодня;
— промокод Agent на скидку 10 000 рублей действует последние часы;
— сразу после оформления открываются материалы для подготовки — начать учиться можно прямо сейчас.

Забронировать место на курсе и забрать бонусы до конца дня
🌚1
Как работает сборщик мусора?

PHP использует два механизма управления памятью: счётчик ссылок (refcount) и циклический сборщик мусора (GC).

Каждая переменная хранит zval с refcount — счётчиком, сколько переменных ссылаются на это значение. Когда refcount падает до 0, память освобождается немедленно.

Проблема возникает при цикличных ссылках:
php$a = [];
$a[] = &$a; // $a ссылается сама на себя
unset($a); // refcount стал 1, а не 0 — утечка


После unset refcount не обнуляется, потому что объект ссылается на самого себя. Простой счётчик это не поймает.

Для таких случаев PHP (с версии 5.3) имеет cyclic garbage collector. Он периодически запускается (или при достижении порога ~10 000 потенциальных "мусорных" zval'ов) и обходит граф ссылок, выявляя изолированные циклы.

Управление вручную:

gc_collect_cycles(); // принудительный запуск
gc_disable(); // отключить, если GC мешает производительности
gc_enable();
gc_status(); // статистика


На практике — актуально в долгоживущих процессах (Swoole, RoadRunner, воркеры), где объекты с взаимными ссылками (например, parent/children в дереве) могут постепенно съедать память. Решение — либо weak references (WeakReference::create($obj)), либо явная очистка связей перед unset.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41🔥1
Что такое Fibers в PHP 8.1 и чем они отличаются от async/await в других языках?

Fiber — примитив для кооперативной многозадачности. Позволяет приостановить выполнение функции в произвольной точке через Fiber::suspend() и возобновить позже, передав значение обратно.

Главное отличие от async/await: Fibers не заражают сигнатуры. В JS как только где-то await — вся цепочка выше должна быть async. В PHP Fiber::suspend() можно вызвать на любой глубине стека, не меняя сигнатуры вызывающих функций.

Второе отличие — Fibers это низкоуровневый примитив, event loop в них не встроен. Сами по себе они не дают параллелизма — это строительный блок, поверх которого ReactPHP, Revolt и Amp строят настоящую неблокирующую конкурентность.
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍4🔥3
В чём разница между interface и abstract class?

Interface — это контракт. Только сигнатуры методов, никакой реализации (до PHP 8 — вообще, в 8+ можно константы). Класс может имплементировать сколько угодно интерфейсов.

Abstract class — частичная реализация. Можно миксовать абстрактные методы с готовыми, хранить состояние (свойства). Наследование — только одно.

🔹 Когда interface:
— описываешь поведение, не связанное иерархией (Loggable, Serializable, Cacheable)
— хочешь возможность имплементировать несколько контрактов

🔹 Когда abstract class:
— есть общий код, который не хочешь дублировать
— классы реально связаны иерархически (BaseRepository, BaseCommand)

На практике — предпочитай интерфейс + trait вместо абстрактного класса. Получаешь гибкость множественного наследования поведения без жёсткой иерархии.
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍3🔥1
Чем PHP-FPM отличается от RoadRunner/Swoole?

PHP-FPM — это share-nothing. Nginx принимает запрос, передаёт его свободному worker-процессу, тот поднимается с нуля (или берётся из пула), отрабатывает, умирает (или возвращается в пул чистым). Всё: globals, static, состояние контейнера — сброшено.

RoadRunner — это Go-сервер, который держит PHP-воркеры живыми между запросами через бинарный протокол (на основе goridge). Swoole — PHP-расширение, которое само реализует event loop и корутины прямо в процессе. Оба дают одно: bootstrap выполняется один раз, дальше worker просто принимает запросы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍81
Как работает Service Container в Laravel и зачем он нужен?

Это IoC-контейнер, который управляет зависимостями и их разрешением. Главная задача — инверсия управления: ты не создаёшь объекты через new, а просишь контейнер их предоставить.

Работает в два шага: binding и resolving.

// Binding — регистрируем, как создавать
app()->bind(PaymentInterface::class, StripePayment::class);

// Resolving — контейнер сам строит граф зависимостей
$payment = app(PaymentInterface::class);


Когда ты тайпхинтишь зависимость в конструкторе контроллера, контейнер видит это через Reflection API и автоматически подтягивает нужные классы, рекурсивно разрешая все вложенные зависимости.

Есть три вида байндингов

bind — новый инстанс при каждом резолве
singleton — один инстанс на весь request lifecycle
instance — регистрируешь уже созданный объект
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥41👍1
Что такое preloading в PHP и какие у него ограничения?

Preloading (PHP 7.4+) — механизм, при котором PHP загружает файлы в память один раз при старте PHP-FPM и держит их там на весь срок жизни процесса. Последующие запросы используют уже скомпилированный opcode без обращения к диску.

▪️ Что даёт

— Устраняет overhead на парсинг и компиляцию горячих классов
— Реальный прирост на больших фреймворках (Laravel, Symfony) — 10–30% к RPS

▪️ Ограничения

— При любом изменении файла нужен рестарт PHP-FPM, иначе изменения не подхватятся.
— Preloaded классы нельзя пересоздать или переопределить в рантайме
— Если preloaded класс зависит от другого файла, тот тоже должен быть preloaded, иначе ошибка при старте
— Не работает с circular dependencies между файлами
— Работает только с OPcache
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1🤔1
✔️ PHP-тест: Fibers + замыкания в Laravel

Классическая ловушка с утечкой состояния 👇

📦 Задание

Написали систему обработки платёжных webhook'ов. В логах периодически замечают, что у одной транзакции записывается merchant_id другой. Баг плавающий, воспроизводится только под нагрузкой. Найдите проблему и исправьте:

class MerchantContext
{
private static ?string $currentMerchantId = null;

public static function set(string $id): void
{
self::$currentMerchantId = $id;
}

public static function get(): ?string
{
return self::$currentMerchantId;
}

public static function clear(): void
{
self::$currentMerchantId = null;
}
}

class WebhookProcessor
{
public function handle(WebhookPayload $payload): void
{
MerchantContext::set($payload->merchantId);

$fiber = new Fiber(function () use ($payload): void {
$result = $this->validateSignature($payload);

// симулируем I/O — запрос к внешнему сервису
Fiber::suspend();

$this->auditLogger->log(
'Webhook processed for: ' . MerchantContext::get(),
['amount' => $payload->amount]
);
});

$fiber->start();
// ... другие файберы запускаются здесь
$fiber->resume();
}
}


🔹 Задачи

— Объяснить, почему MerchantContext::get() после resume() может вернуть merchant_id другого запроса
— Исправить так, чтобы контекст не терялся при переключении между файберами

Ставьте → 🔥 если нравится формат. Если нет → 🌚

💬 Решения пишите в комменты под спойлер — сравним подходы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17👍1🤔1
Что такое Closure и зачем нужен use?

Closure — это анонимная функция. Объект класса Closure под капотом.
use захватывает переменные из внешнего скоупа внутрь замыкания.

$discount = 10;

$price = fn($amount) => $amount - $discount; // не работает

$price = function($amount) use ($discount) {
return $amount - $discount; // работает
};
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1😢1🥱1👾1
Какие HTTP-методы есть?

GET: этот метод используется для запроса содержимого указанного ресурса.

POST: обычно используется для отправки данных формы или для выполнения какой-то операции на сервере, которая может изменить состояние сервера или добавить новые данные.

PUT: используется для создания или обновления ресурса на сервере.

DELETE: удалить указанный ресурс с сервера.

PATCH: используется для частичного обновления ресурса.

HEAD: метод полезен, когда клиенту нужны только заголовки, а не фактическое содержимое.

OPTIONS: получить информацию о возможностях сервера относительно ресурса или сервера в целом. Это может включать доступные методы, поддерживаемые заголовки и другую метаинформацию.

TRACE: используется для тестирования соединения между клиентом и сервером. Когда сервер получает запрос TRACE, он возвращает весь запрос обратно клиенту, что позволяет клиенту увидеть, как запрос проходит через промежуточные узлы.

CONNECT: используется для установки виртуального соединения с сервером, обеспечивая прозрачное шифрование SSL через промежуточный узел.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
В чем разница между '==' и '===' ?

Нестрогое сравнение («==»): При использовании двойного знака равенства PHP сравнивает значения операндов после их преобразования в общий тип данных. Например, 5 == '5' вернет true, потому что PHP преобразует строку '5' в целое число 5 перед сравнением.

Строгое сравнение («===»): При использовании тройного знака равенства PHP сравнивает не только значения операндов, но и их типы данных. Это означает, что для того чтобы выражение было истинным, значения операндов должны быть одинаковыми и одного типа. Например, 5 === '5' вернет false, потому что типы операндов различны.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
☝️ Уже сегодня: ИИ-агенты в продакшене — инженерный подход к интеграции LLM

Индустрия активно обсуждает потенциал нейросетей, способных автоматизировать бизнес-процессы и заменить целые отделы. Однако реальное внедрение агентов в production вскрывает серьёзные проблемы: разработчикам приходится бороться с непредсказуемыми галлюцинациями моделей, нестабильными API и сложной интеграцией в существующую архитектуру.

Сегодня в 19:00 МСК в рамках нашего курса «Разработка AI-агентов» мы проведём открытый вебинар «ИИ-агенты в продакшене: от хайпа к деньгам». Спикер — Полина Полунина, руководитель AI-направления в Альфа-Банке. Будем говорить о нейросетях с позиции жёсткой инженерии.

Разберём три реальных кейса из сурового банковского энтерпрайза, напишем и запустим агента прямо в эфире, честно обсудим грабли, на которые наступает бизнес при интеграции LLM.

Тем, кто придёт на эфир, дадим промокод AGENTS на скидку 10 000 ₽ на любой тариф курса.

👉 Занять место на вебинаре
🥱1
Часовая готовность: создаём ИИ-агента в прямом эфире

В 19:00 МСК в рамках нашего курса «Разработка AI-агентов» стартует вебинар «ИИ-агенты в продакшене: от хайпа к деньгам». Спикер — Полина Полунина, руководитель AI-направления в Альфа-Банке.

Будет live-демо работающего агента, реальные метрики из корпоративной среды и честный разбор архитектурных граблей — без воды и «успешного успеха».

Всем зрителям эфира дадим эксклюзивный промокод AGENTS на скидку 10 000 ₽ на любой тариф курса.

👉 Занять место на вебинаре
🥱1
Чем отличается абстрактный класс от интерфейса?

Интерфейс — чистый контракт. Только сигнатуры методов и константы, никакой реализации. Класс может реализовывать сколько угодно интерфейсов.

Абстрактный класс — уже частичная реализация: может содержать конкретные методы, свойства, конструктор. Наследоваться можно только от одного.

Правило выбора простое: если нужно описать что умеет объект — интерфейс. Если нужно вынести общую логику и состояние — абстрактный класс.

В хорошей архитектуре они часто работают вместе: абстрактный класс реализует интерфейс частично, потомки добивают остальное.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
Что такое trait и зачем он нужен, если есть абстрактные классы?

Trait — механизм горизонтального переиспользования кода. PHP не поддерживает множественное наследование, trait это обходит: он буквально копирует методы в класс на этапе компиляции. Класс может использовать несколько трейтов одновременно.

Хорошо подходит для сквозной функциональности: логирование, soft delete, timestamps, работа с UUID. Плохо — когда трейт начинает зависеть от свойств класса, которые в нём не объявлены. Это скрытая связанность, и трейтами легко злоупотребить. Если видишь трейт с $this->connection без объявления свойства — это запах.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🥱2🔥1😁1
Что такое PSR-4?

Стандарт автозагрузки классов от PHP-FIG. Описывает как неймспейс маппится на структуру директорий. Composer реализует его из коробки через секцию autoload в composer.json.

Суть: App\Services\PaymentService должен лежать в src/Services/PaymentService.php, если корневой неймспейс App\ смаплен на src/. Без этого стандарта каждый фреймворк изобретал свой автолоадер. PSR-4 заменил устаревший PSR-0 и сейчас де-факто обязателен в любом современном PHP-проекте.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3
✔️ PHP-тест: Static state + OPcache + Preloading

Классический баг, который ломает прод и не воспроизводится локально 👇

📦 Задание

Команда добавила preloading в production для ускорения.

Через день в логах появились странные ошибки: у разных пользователей в одном запросе перемешиваются данные — кто-то видит чужие настройки, кто-то получает null там, где не должен.

На dev-машинах не воспроизводится. Найдите проблему в коде:
// preload.php 
require_once 'src/Config.php';
require_once 'src/UserContext.php';
require_once 'src/RequestPipeline.php';

// config/app.php
class Config
{
private static array $data = [];
private static bool $loaded = false;

public static function load(string $env): void
{
if (self::$loaded) {
return;
}
self::$data = parse_ini_file("config/{$env}.ini");
self::$loaded = true;
}

public static function get(string $key): mixed
{
return self::$data[$key] ?? null;
}
}

// src/UserContext.php
class UserContext
{
private static ?array $current = null;

public static function set(array $user): void
{
self::$current = $user;
}

public static function get(): ?array
{
return self::$current;
}

public static function clear(): void
{
self::$current = null;
}
}

// src/RequestPipeline.php
class RequestPipeline
{
private static array $middlewareResults = [];

public static function addResult(string $key, mixed $value): void
{
self::$middlewareResults[$key] = $value;
}

public static function getResult(string $key): mixed
{
return self::$middlewareResults[$key] ?? null;
}

public static function reset(): void
{
self::$middlewareResults = [];
}
}

// public/index.php
Config::load($_ENV['APP_ENV'] ?? 'production');

$user = Auth::check($_SERVER['HTTP_AUTHORIZATION'] ?? '');
UserContext::set($user);

RequestPipeline::addResult('ip', $_SERVER['REMOTE_ADDR']);
RequestPipeline::addResult('ua', $_SERVER['HTTP_USER_AGENT'] ?? '');

$app->handle(ServerRequest::fromGlobals());


🔹 Задачи

— Объяснить, почему при preloading статические свойства классов ведут себя иначе, чем без него, и как это связано с жизненным циклом worker-процесса.
— Объяснить, чем классы отличаются по характеру утечки
— Предложить архитектурное решение: как правильно управлять request-scoped состоянием в long-running процессах

Ставьте → 🔥 если нравится формат. Если нет → 🌚

💬 Решения пишите в комменты под спойлер — сравним подходы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍2🤔2🥱1