Библиотека собеса по PHP | вопросы с собеседований
Открыть в Telegram
Вопросы с собеседований по PHP и ответы на них. По рекламе: @proglib_adv Учиться у нас: clc.to/5JWKxA Для обратной связи: @proglibrary_feeedback_bot
Больше3 114
Подписчики
-324 часа
-67 дней
-1930 день
Архив постов
❓ Расскажите о паттерне Singleton?
Singleton — это порождающий паттерн проектирования, который гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к нему.
🔹 Основные характеристики:
— приватный конструктор запрещает создание экземпляров извне;
— статический метод getInstance() возвращает единственный экземпляр;
— статическое поле для хранения экземпляра.
🔹 Когда использовать:
— объект содержит глобальное состояние;
— создание объекта ресурсозатратно;
— нужен единый координатор действий;
— логически должен быть один экземпляр.
❓ Расскажите о паттерне Strategy?
Strategy — это поведенческий паттерн, который позволяет определить семейство алгоритмов, инкапсулировать каждый из них и сделать их взаимозаменяемыми.
Когда использовать:
— есть несколько способов выполнения одной операции;
— нужно избежать множественных if-else или switch;
— алгоритмы должны выбираться в runtime.
Преимущества: соблюдение Open/Closed Principle, устранение условных операторов, гибкость выбора алгоритма
✔️ PHP-тест: Утечка сессии между пользователями
Баг не воспроизводится локально. На проде один юзер видит чужие данные 👇
📦 Задание
Стартап запустил SaaS. Первые две недели тишина. А потом в поддержку прилетело: «Я зашёл в кабинет и увидел чужой аккаунт». В коде сессий и авторизации не трогали давно, там всё стабильно.
// src/Auth/UserSession.php
class UserSession
{
private static ?User $currentUser = null;
public static function set(User $user): void
{
self::$currentUser = $user;
}
public static function get(): ?User
{
return self::$currentUser;
}
public static function clear(): void
{
self::$currentUser = null;
}
}
// src/Middleware/AuthMiddleware.php
class AuthMiddleware
{
public function __construct(
private readonly UserRepository $userRepository,
private readonly JWTService $jwt,
) {}
public function handle(Request $request, callable $next): Response
{
$token = $request->headers->get('Authorization');
if (!$token) {
return new Response(status: 401);
}
$payload = $this->jwt->decode(str_replace('Bearer ', '', $token));
$user = $this->userRepository->find($payload['sub']);
UserSession::set($user);
return $next($request);
}
}
// src/Controller/DashboardController.php
class DashboardController
{
public function index(): Response
{
$user = UserSession::get();
return new Response(
body: $this->renderDashboard($user),
);
}
}
// src/Console/CacheWarmupCommand.php
class CacheWarmupCommand
{
public function execute(): void
{
$users = $this->userRepository->findAll();
foreach ($users as $user) {
UserSession::set($user);
$this->warmupForUser($user);
}
// прогрев завершён
}
}
🔹 Задачи
— Объяснить механизм утечки
— Объяснить, как CacheWarmupCommand триггерит баг и при каком race window
— Переписать UserSession так, чтобы устранить проблему архитектурно, а не патчем
Ставьте → 🔥 если нравится формат. Если нет → 🌚
💬 Решения пишите в комменты под спойлер — сравним подходы.❓ Что такое Bundles в Symfony?
В Symfony, Bundle — это структурированный набор файлов и директорий, реализующих определённую функцию или набор связанных функций. Бандлы являются основными единицами организации, позволяя упаковывать повторно используемый код и делиться им между несколькими проектами.
Ключевые аспекты
1️⃣ Структура и организация
Бандлы предоставляют способ организовать код в логические единицы. Каждый бандл обычно включает:
— Контроллеры
— Модели/Сущности
— Сервисы
— Конфигурационные файлы
— Шаблоны (файлы Twig)
— Информацию о маршрутах
2️⃣ Повторное использование
Бандлы могут быть повторно использованы в разных проектах. Это упрощает совместное использование и распространение функций и функциональных возможностей, способствуя модульности и поддерживаемости.
3️⃣ Разделение
Бандлы помогают разделить различные части приложения. Это разделение гарантирует, что изменения в одном бандле не влияют на функциональность других, что облегчает обслуживание и разработку.
4️⃣ Сторонние бандлы
У Symfony есть богатая экосистема сторонних бандлов, доступных через такие платформы, как Packagist. Эти бандлы можно легко интегрировать в проект для добавления различных функций, таких как аутентификация пользователей, обработка платежей или интеграция с API.
❓ Что такое Bundles в Symfony?
В Symfony, Bundle — это структурированный набор файлов и директорий, реализующих определённую функцию или набор связанных функций. Бандлы являются основными единицами организации, позволяя упаковывать повторно используемый код и делиться им между несколькими проектами.
Некоторые ключевые аспекты:
1. Структура и организация
Бандлы предоставляют способ организовать код в логические единицы. Каждый бандл обычно включает:
✔️Контроллеры
✔️Модели/Сущности
✔️Сервисы
✔️Конфигурационные файлы
✔️Шаблоны (файлы Twig)
✔️Информацию о маршрутах
2. Повторное использование
Бандлы могут быть повторно использованы в разных проектах Symfony. Это упрощает совместное использование и распространение функций и функциональных возможностей, способствуя модульности и поддерживаемости.
3. Разделение
Бандлы помогают разделить различные части приложения. Это разделение гарантирует, что изменения в одном бандле не влияют на функциональность других, что облегчает обслуживание и разработку.
4. Сторонние бандлы
У Symfony есть богатая экосистема сторонних бандлов, доступных через такие платформы, как Packagist. Эти бандлы можно легко интегрировать в ваш проект для добавления различных функций, таких как аутентификация пользователей, обработка платежей или интеграция с API.
5. Конфигурация
Бандлы могут быть настроены с помощью файлов конфигурации YAML, XML или PHP. Это позволяет настроить поведение бандла в соответствии с потребностями вашего приложения.
6. Лучшие практики
Symfony рекомендует использовать стандартную структуру директорий для бандлов, которая включает:
Controller/: Содержит классы контроллеров.
Resources/config/: Содержит конфигурационные файлы.
Resources/views/: Содержит шаблоны Twig.
Resources/public/: Содержит общедоступные ресурсы, такие как CSS и JavaScript файлы.
DependencyInjection/: Содержит классы и конфигурации, связанные с внедрением зависимостей.
Entity/: Содержит классы сущностей Doctrine.
Осталось всего 4 места на курс по ИИ-агентам. 30 апреля закрываем набор окончательно.
В ГС честно рассказали:
— Кому курс не подойдет;
— Какой хардкор в программе (LangGraph, AutoGen, CrewAI);
— Как мы даем токены, чтобы вы не тратили свои деньги.
🏃♀️ Записаться, пока есть места
❓ Symfony основан на конфигурации или соглашениях?
Symfony — это фреймворк, основанный на соглашениях. Документ Coding Standards иллюстрирует нормы кодирования для проектов Symfony, а также внутренних и сторонних пакетов. Он определяет стандарты кодирования и соглашения, используемые в ядре фреймворка, чтобы сделать его более единообразным и предсказуемым.
❓ Как отревьюить большой PR?
Большой PR — это архитектурная проблема, но раз он уже есть, вот стратегия:
🔹 Начинать не с первого файла в списке, а с точки входа — контроллера, команды или сервиса, где меняется логика.
🔹 До открытия первого файла — ответить на три вопроса: что должно измениться в поведении системы, что не должно, и где граница между старым и новым.
🔹 Тесты читать первыми, т.к. они документируют намерение автора лучше, чем любой комментарий.
🔹 Искать не ошибки, а допущения. Где код предполагает, что данные всегда валидны? Что очередь не упадёт? Что транзакция атомарна? Именно здесь прячутся баги, которые выстреливают через месяц.
🔹 Замечания по стилю без линтера — не тема для PR-комментариев. Если в проекте нет phpcs или php-cs-fixer, лучше их настроить, чем воевать в ревью.
❓ Ты деплоишь новую версию. Половина серверов на старом коде, половина на новом. Как не сломать пользователей?
Три зоны ответственности — три правила:
🔹 БД — только аддитивные миграции. Не удалять, не переименовывать колонки в том же деплое. Сначала добавь — потом убери старое отдельным деплоем.
🔹 API — не меняй формат ответа, только расширяй. Сломал контракт — версионируй (/v2/).
🔹 Очереди — не меняй свойства Job-классов, только добавляй. Старый воркер может достать джоб от нового кода.
Главное: feature flags вместо big bang деплоя. Код едет отдельно от включения фичи.
❓ Что такое WeakReference и WeakMap?
WeakReference — ссылка на объект, не увеличивающая счётчик ссылок. Объект может быть уничтожен GC, тогда ->get() вернёт null.
WeakMap (PHP 8.0) — map с объектами в роли ключей, тоже не удерживает объекты от GC. При уничтожении объекта-ключа запись автоматически исчезает.
$map = new WeakMap();
$obj = new stdClass();
$map[$obj] = 'data';
unset($obj);
// запись в $map исчезла сама
Можно применять: кэши метаданных об объектах (атрибуты, вычисленные значения), без риска утечки памяти. Активно используется в Symfony, Doctrine.🔄Вы используете шаблоны, запросы и конфигурации каждый день. Но понимаете ли вы, как они устроены внутри?
📅На открытом уроке за 60 минут разберём, как работает любой язык — и соберём свой DSL на PHP. Покажем полный конвейер: от исходного текста до результата. Вы увидите, как писать лексер, строить синтаксическое дерево и реализовывать интерпретатор.
Всё — на чистом PHP, без магии и скрытых механизмов. Это даёт не просто новый навык, а понимание, как работают инструменты, которыми вы уже пользуетесь: шаблонизаторы, запросы, правила. И как создавать собственные решения под задачи бизнеса — без хардкода и сложных обходных путей.
💡Открытый урок проходит в преддверии старта курса «PHP-разработчик. Продвинутый уровень» 29 апреля в 20:00 МСК. Регистрация: https://clc.to/IA9gbg
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
❓ В чём разница между static и self в PHP?
self — ссылается на класс, в котором метод определён (compile-time).
static — ссылается на класс, из которого метод вызван (runtime, late static binding).
class A {
public static function create(): static {
return new static(); // вернёт экземпляр B, если вызвано из B
}
}
class B extends A {}
B::create(); // → объект B, не A❓ Что такое Lazy Collections в Laravel?
Обычная Collection загружает всё в память сразу. При работе с большими объёмами данных — это проблема.
// ❌ Загрузит ВСЕ записи в память
$users = User::all()->filter(...)->map(...);
// ✅ Lazy Collection — обрабатывает по одной записи через генератор
User::cursor()->filter(function (User $user) {
return $user->is_active;
})->each(function (User $user) {
ProcessUser::dispatch($user);
});
cursor() использует PDO fetchRow под капотом — в памяти одновременно одна запись.
Lazy Collection из файла:
// Обработка огромного CSV без OutOfMemoryError
$collection = LazyCollection::make(function () {
$handle = fopen('huge_file.csv', 'r');
while ($row = fgetcsv($handle)) {
yield $row;
}
});
$collection->skip(1)->chunk(100)->each(function ($rows) {
ImportBatch::dispatch($rows->toArray());
});
Когда использовать
— 10k+ записей в обработке → cursor() + LazyCollection
— Файлы, стримы, внешние API с пагинацией → LazyCollection с генератором
Важно: методы типа count() и last() материализуют коллекцию. Их лучше избегать в lazy-контексте.❓ Чем SplDoublyLinkedList, SplMinHeap и SplFixedArray отличаются от обычного array?
PHP array — это хэш-таблица с упорядоченными ключами. Универсальна, но каждый элемент занимает ~400–500 байт в zval + hashtable bucket. SPL-структуры — специализированные контейнеры с фиксированной семантикой и меньшим оверхедом.
SplFixedArray — C-массив фиксированного размера. Занимает в 3–4 раза меньше памяти. Оправдан, когда размер известен заранее.
// array: ~400 MB
$arr = array_fill(0, 1_000_000, 0);
// SplFixedArray: ~90 MB
$fixed = new SplFixedArray(1_000_000);
SplDoublyLinkedList / SplStack / SplQueue — двусвязный список под капотом. Выигрывает при частых вставках и удалениях в середину. При случайном доступе по индексу — проигрывает array: O(n) против O(1).
SplMinHeap / SplMaxHeap — бинарная куча. Классический кейс — приоритетная очередь с извлечением минимума/максимума за O(log n).
$heap = new SplMinHeap();
$heap->insert(5);
$heap->insert(1);
$heap->insert(3);
// Всегда достаёт минимум за O(log n)
echo $heap->extract(); // 1
echo $heap->extract(); // 3
⚠️ На что обратить внимание на практике
→ SplFixedArray не поддерживает строковые ключи и array_* функции — только числовые индексы
→ В PHP 8.1+ SplFixedArray реализует IteratorAggregate — работает в foreach без обёрток
→ Для задач "top-K элементов" или Dijkstra — SplMinHeap бьёт usort по всем фронтам
→ В большинстве бизнес-задач обычный array быстрее за счёт CPU-кэша — SPL оправдан при сотнях тысяч элементов🏃♀️ Мы собрали бесплатный мега-гайд по ии-агентам 👇
В первой части постов навалили жесткой базы, чтобы вправить мозги на место. Во второй дали конкретные инструменты, фреймворки и пошаговые инструкции, что нужно кодить прямо сейчас.
Часть 1. Введение, юзкейсы и реальность
Разбираемся с терминами, снимаем розовые очки и смотрим, где ИИ реально приносит бабки, а где только жжет нервы:
1. «Так что вообще считается AI-агентом?»
2. «Где тут бот, а где уже AI-агент?»
3. «Не надо пихать AI-агента в каждую задачу»
4. «Что уже можно спокойно делать через AI-агентов?»
5. «А что через AI-агентов пока лучше не трогать?»
Часть 2. Изнанка, ошибки и архитектура
Как всё это устроено под капотом, чтобы не слить бюджет и не наломать дров на старте:
6. «Можно ли просто сесть вечером и собрать себе AI-агента?»
7. «С чего вообще начать, если хочется попробовать AI-агентов»
8. «Почему AI-агент может внезапно начать творить дичь»
9. «Где AI-агенты реально экономят время, а где только добавляют возни»
10. «Почему они жрут столько денег?»
Часть 3. Хардкорная практика (Что делать руками)
Хватит теории. Открываем ноут, запускаем Cursor и делаем нормальные, отказоустойчивые системы:
11. «Почему одного промпта мало?»
12. «Почему AI-агенту мало просто “дать доступ к данным”»
13. «Если не следить за AI-агентом, он быстро начинает жить своей жизнью»
14. «Собрать демку легко. Но как же сделать нормально»
15. «Как сделать, чтобы это не развалилось через неделю?»
👍 Сохраняйте пост в избранное, чтобы не потерять.
🤫 А завтра стартует наш курс по ии-агентам
❓ PHP использует подсчёт ссылок для сборки мусора. В каком случае это может не сработать?
PHP уничтожает объект, когда его refcount падает до 0. Но есть исключение — циклические ссылки: объект A ссылается на B, B — на A. Каждый держит счётчик ≥ 1, хотя оба недостижимы из кода.
Для этого существует Cycle Collector (zval garbage collector). Он запускается не сразу, а когда буфер подозрительных zval заполняется (~10 000 узлов по умолчанию). До его запуска объекты в цикле живут в памяти, даже если логически мертвы.
❓ Как правильно протестировать?
У вас есть два класса:
class A {
public function __construct(private B $b) {}
public function doSomething(): string {
return $this->b->getValue();
}
}
class B {
public function getValue(): string {
return 'real';
}
}
❓ Нужно написать юнит-тест для A::doSomething(), не трогая класс B. Как это сделать правильно?
Создаём мок через PHPUnit, он реализует интерфейс (или наследует класс) и позволяет изолировать зависимость:
$mockB = $this->createMock(B::class);
$mockB->method('getValue')->willReturn('mocked');
$a = new A($mockB);
$this->assertSame('mocked', $a->doSomething());
Почему работает: createMock() генерирует анонимный класс, расширяющий B. PHP позволяет передать его туда, где ожидается B.Symfony Workflow: конечный автомат для реализации бизнес-логики. Бесплатный урок курса «Symfony Framework»
Во многих приложениях бизнес-логика держится на статусах: заказ создан, оплачен, отправлен, доставлен. Пока таких состояний мало, всё кажется простым. Но как только процесс растёт, цепочки
if/else начинают расползаться по проекту, логика дублируется, а добавление нового статуса превращается в риск для всей системы.
📅 На открытом уроке 22 апреля:
— Разберём, как использовать Symfony Workflow для формализации бизнес-процессов через конечный автомат.
— Покажем, чем конечный автомат отличается от рабочего процесса, когда применять каждый подход, как описывать состояния и переходы в YAML и как Symfony умеет автоматически визуализировать процесс.
— На практическом примере рассмотрим сущность заказа со статусами new → paid → shipped → delivered, методы can() и apply(), а также построение схемы состояний через workflow:dump.
Урок не для тех, кто считает, что строковое поле status и набор if/else — это нормальная архитектура «на вырост», и не для тех, кто не работает со сложной бизнес-логикой в приложении.👉 Записаться: https://clc.to/I2zW6A Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
❓ Что такое Job Chaining и Job Batching в Laravel?
Оба механизма для организации нескольких фоновых задач, но логика разная.
Job Chaining — задачи выполняются строго последовательно. Если одна упала, цепочка останавливается:
Bus::chain([
new ProcessPayment($order),
new SendInvoice($order),
new NotifyWarehouse($order),
])->dispatch();
Job Batching — задачи выполняются параллельно, можно отслеживать прогресс и реагировать на завершение всей группы:
$batch = Bus::batch([
new ImportRow($rows->chunk(100)[0]),
new ImportRow($rows->chunk(100)[1]),
new ImportRow($rows->chunk(100)[2]),
])
->then(fn (Batch $batch) => Log::info('Импорт завершён'))
->catch(fn (Batch $batch, Throwable $e) => Log::error('Ошибка'))
->finally(fn (Batch $batch) => Cache::forget('import-lock'))
->dispatch();
// Можно следить за прогрессом
$batch->progress(); // процент выполнения
Когда что
— Независимые задачи, нужна скорость и прогресс → Batch
— Зависимость между задачами, порядок важен → Chain❓ Объясни разницу между Gate и Policy в Laravel?
Оба инструмента для авторизации, но с разной областью применения.
Gate — простые одиночные проверки, не привязанные к модели:
// Определяем в AuthServiceProvider
Gate::define('access-admin-panel', function (User $user) {
return $user->is_admin;
});
// Проверяем
if (Gate::allows('access-admin-panel')) { ... }
// или в контроллере
$this->authorize('access-admin-panel');
Policy — класс с набором правил для конкретной модели:
// php artisan make:policy PostPolicy --model=Post
class PostPolicy
{
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
public function delete(User $user, Post $post): bool
{
return $user->id === $post->user_id || $user->is_admin;
}
}
// Использование
$this->authorize('update', $post);
Правило выбора
— Нет модели → Gate
— Есть модель, несколько действий → Policy