Вопросы на собеседовании: PHP-разработчик
100 реальных вопросов с образцовыми ответами и пояснениями для уровня Senior PHP-разработчик.
Смотреть пример резюме: PHP-разработчик →Тренировка флешкарточками
Интервальное повторение · Hunter Pass
Вопросы
Я выделю один checkout use case за inbound и outbound ports, оставив существующие controllers HTTP adapters.
- Инварианты order помещу в domain objects, orchestration в application service, а для payment, order persistence и event publication определю ports.
- Laravel adapters реализуют ports через Eloquent, Stripe и RabbitMQ, а service container связывает их только на composition edge.
- Сначала мигрирую один endpoint и потребую, чтобы его domain tests запускались без boot Laravel и подключения к трём внешним системам.
Зачем это спрашивают: Интервьюер проверяет incremental hexagonal design с enforceable dependency direction.
Я заменю framework types на границе одного часто меняемого use case входной command-моделью и явным result.
- Controller преобразует Request data в validated command, а application service никогда не импортирует HttpFoundation.
- Repository преобразует Doctrine entities в domain objects или read projections, поэтому lazy-loading proxies не попадают в serialization.
- Dependency check в CI запрещает imports Symfony и Doctrine из domain и application namespaces после каждого мигрированного use case.
Зачем это спрашивают: Сильный ответ превращает layers в проверяемые компилятором boundaries вместо названий каталогов.
Я создам отдельные bounded-context models, потому что два понятия Order имеют разные invariants и lifecycles.
- Billing владеет payable order и публикует OrderPaid со stable order ID, amount, currency и event version.
- Fulfillment принимает contract через anti-corruption mapper и владеет shipment state без imports billing entities или tables.
- Contract tests доказывают понимание version 1 обоими contexts, а context map фиксирует ownership и one-way integration.
Зачем это спрашивают: Интервьюер оценивает DDD boundaries по конфликтующим бизнес-значениям, а не по дублированию classes.
Я сделаю inventory одного SKU consistency boundary и обеспечу reservation invariant одним atomic database transition.
- Aggregate root отвергает reservation выше available quantity и использует version column или conditional update вида available >= requested.
- Application service загружает и сохраняет один SKU aggregate в одной transaction, а order и notification work происходят вне этого lock.
- Concurrent test запускает 20 requests на последние 3 единицы и требует ровно 3 accepted units без negative balance.
Зачем это спрашивают: Сильный ответ связывает domain invariant с atomic persistence mechanism при concurrency.
Я заменю floats на pricing boundary immutable value object Money с integer minor units и currency.
- Construction отвергает mixed currency и invalid precision, а methods add, subtract, tax и allocation явно сохраняют rounding rules.
- Persistence хранит amount_minor и ISO currency, а API adapters преобразуют decimal strings без float conversion.
- Property tests распределяют от 1 до 10 000 cents по максимум 20 lines и требуют точную сумму частей с original amount.
Зачем это спрашивают: Интервьюер проверяет value-object design, устраняющий конкретный numerical invariant failure.
Я оставлю transaction orchestration в application service, а policy и transport decisions передам соответствующим owners.
- Refund aggregate или policy object определяет eligibility и amount из domain values без Response, EntityManager или vendor exceptions.
- Application service загружает aggregate, вызывает refund behavior, один раз commit и записывает outbox event в той же transaction.
- Controller преобразует domain outcomes в HTTP status и error documents, а unit test покрывает 12-step use case с repository и clock fakes.
Зачем это спрашивают: Сильный ответ разделяет domain decisions, use-case coordination, persistence и HTTP mapping.
Я дам каждому module owned schema surface и малый public application API до обсуждения отдельных deployments.
- Cross-module reads используют typed query ports или published projections, а прямые imports entities и repositories другого module запрещены.
- Transactions остаются локальными одному module; workflows между modules используют application orchestration или committed events с явной consistency.
- Deptrac и database-access tests ломают CI при forbidden namespaces или table use, начиная с пяти наиболее изменяемых modules.
Зачем это спрашивают: Интервьюер проверяет modular-monolith boundaries, ограничивающие coupling кода и данных.
Я заменю persistence-shaped methods операциями, названными по domain decisions, которые нужны caller.
- OrderRepository может раскрывать get(OrderId), add(Order) и отдельную overdue-order read projection вместо arbitrary criteria.
- QueryBuilder, ORM entities и flush остаются в Doctrine adapter; transaction ownership остаётся на application boundary.
- Contract tests прогоняют одинаковые repository cases на Doctrine adapter и in-memory fake, включая missing и concurrent-version behavior.
Зачем это спрашивают: Сильный ответ защищает domain semantics вместо маскировки generic ORM gateway под repository.
Я выполню authorization до tenant-sensitive cache lookup, измерю всю operation и буду повторять только safe remote adapter.
- Outer metrics decorator записывает denied, hit, miss, retry и final latency без secret labels.
- Authorization выполняется до cache с key из tenant, actor scope, resource ID и representation version, предотвращая cross-tenant hits.
- Retry оборачивает только idempotent remote call, а не authorization или весь use case, и test проверяет максимум три provider attempts.
Зачем это спрашивают: Интервьюер оценивает порядок decorators через последствия для security, observability и idempotency.
Я опубликую versioned domain fact со stable business identifiers и values, а не ORM snapshot.
- Version 1 содержит event_id, order_id, customer_id, occurred_at, total minor units и currency с документированными required fields.
- Aggregate записывает event после прохождения invariant, а transactional outbox сохраняет его вместе с order commit.
- Consumer contract tests декодируют historical version-1 fixtures, а schema evolution совместимо добавляет fields или вводит новую event version.
Зачем это спрашивают: Сильный ответ рассматривает domain events как durable integration contracts, независимые от database layout.
Я рассчитаю OPcache по измеренным used memory, wasted memory, interned strings, file count и росту release, а не default template.
- При 190 МБ compiled code начну с 256 МБ, около 25% headroom, и max_accelerated_files выше 25 000, например 40 000.
- Буду следить через opcache_get_status за cache_full, wasted_percentage, misses и restart counters на production release artifact.
- 60-minute load test должен дать ноль capacity restarts и hit rate выше 99,9% до выпуска settings.
Зачем это спрашивают: Интервьюер проверяет quantitative OPcache sizing по bytecode и file evidence.
Я разверну один immutable artifact и gracefully заменю каждый PHP process вместо опоры на file timestamp checks.
- Composer optimized autoload и framework caches собираются один раз в CI внутри versioned release directory.
- Symlink или container image переключается atomically, затем PHP-FPM и long-running workers drain и restart на одном release ID.
- Health checks сообщают release ID и загружают representative classes; traffic расширяется только после 100% workers на новом artifact.
Зачем это спрашивают: Сильный ответ связывает disabled revalidation с process lifecycle и atomic immutable deployment.
Я оставлю только измеренный hot preload set, если 12 мс существенно улучшают latency objective после учёта memory и deployment cost.
- Blackfire call counts найдут framework и domain files, загружаемые почти в каждом request, вместо preload всего vendor tree.
- Сравню worker density, master shared memory, cold restart time и p95 latency без preload, с set 40 МБ и текущим set 420 МБ.
- Выберу минимальный set, выполняющий target, и потребую graceful master restart в deploy и rollback runbooks.
Зачем это спрашивают: Интервьюер оценивает preload как измеренный trade-off latency, memory и deployment.
Я ожидаю малый выигрыш request latency, потому что JIT не оптимизирует ожидание database или network.
- Сравню тот же traffic с одним OPcache и с JIT, записывая CPU, p50, p95, p99, memory и throughput.
- Отдельный CPU-bound pricing simulation с 50 миллионами arithmetic operations может выиграть и подходит для оценки JIT.
- Оставлю JIT выключенным для API, если он не улучшает p95 или CPU минимум на согласованный threshold без снижения worker density.
Зачем это спрашивают: Сильный ответ ограничивает ожидания от JIT CPU-bound PHP execution и требует representative evidence.
Я профилирую representative slow checkout и оптимизирую dominant inclusive cost до введения ещё одного cache.
- Сравню wall time, CPU, I/O wait, call count и memory для того же payload с baseline 780 мс.
- Если 430 мс уходят на 101 Doctrine queries, сначала исправлю access pattern и index; caching final response скрыл бы correctness, зависящую от writes.
- Сохраню scenario с assertions на query count ниже 10 и p95 ниже 250 мс как regression gate.
Зачем это спрашивают: Интервьюер проверяет measurement-led optimization и правильную трактовку profiler call graphs.
Я использую Xdebug только на одном controlled identical input и буду трактовать proportions calls, а не искажённый wall time.
- Cachegrind покажет call counts, inclusive cost и self cost и выделит dominant formatting, hydration или algorithm.
- Подтвержу выбранный hotspot low-overhead timer или Blackfire run до заявления о production gain.
- Optimized report должен быть быстрее original baseline 42 секунды в трёх Xdebug-free runs с одинаковыми output checksums.
Зачем это спрашивают: Сильный ответ учитывает profiler observer overhead и проверяет результат по uninstrumented baseline.
Я буду потоково читать bounded result batches и записывать output incrementally вместо materialization 2 миллионов rows.
- Использую keyset batches или unbuffered PDO cursor, где позволяет driver, выбирая только columns, нужные export.
- Обрабатываю 1 000-5 000 rows, освобождаю ORM state через clear при необходимости и flush output stream после каждого batch.
- Полный fixture остаётся ниже 200 МБ peak, сохраняет row count и checksum и избегает long transaction, блокирующей cleanup.
Зачем это спрашивают: Интервьюер оценивает PHP memory behavior, database cursors и bounded export design.
Memory допускает около 68 children, но я ограничу pool примерно 56, потому что database connection budget жёстче.
- Memory ceiling равен floor(12 288/180)=68, поэтому нет смысла задавать children больше downstream concurrency.
- Оставлю четыре database connections для queue или maintenance work и проверю, может ли каждый child держать persistent connection.
- Проведу load test 56 children по FPM listen queue, RSS, CPU, database waits и p99 latency, затем настрою по measured saturation.
Зачем это спрашивают: Сильный ответ выполняет memory calculation и затем соблюдает меньший downstream connection budget.
Я использую dynamic mode с малым warm floor, чтобы ограничить idle memory без cold-start burst на 80 processes.
- Настрою start_servers и min_spare_servers под observed burst ramp, а max_children по-прежнему ограничу memory и database.
- Static подходит continuously busy predictable pool, а ondemand остаётся для действительно редких endpoints, допускающих spawn latency.
- Burst test после десяти idle minutes должен держать p95 ниже admin SLO без spawn storm и превышения approved idle RSS.
Зачем это спрашивают: Интервьюер проверяет выбор process manager по конкретному traffic и cold-start pattern.
Workload требует 1,67 busy workers, поэтому я начну с четырёх: три дают 50% headroom, один остаётся failure reserve.
- Arrival rate равен 8,33 jobs/s, а 8,33×0,2 секунды дают 1,67 concurrent workers при average service time.
- Проверю p95 job duration и downstream connection use, потому что tail в 1 секунду делает average calculation небезопасным.
- Soak test должен держать oldest-job age ниже target после остановки одного worker и database ниже 70% connection budget.
Зачем это спрашивают: Сильный ответ рассчитывает queue concurrency и добавляет явные headroom и failure capacity.
Закрытые вопросы
- 21
RabbitMQ повторно доставляет invoice job после commit invoice, потому что worker умер до ack. Как предотвратить второй invoice?
- 22
Failed webhook job повторяется каждую секунду, достигает 25 000 attempts и продолжает получать 422 от provider. Как его классифицировать и направить?
webhooks - 23
Восемь workers обрабатывают account events не по порядку, и BalanceUpdated version 42 приходит раньше version 41. Как сохранить required ordering?
concurrency - 24
Symfony Messenger worker должен обработать 20 000 messages и остаться ниже 180 МБ. Какую reset и recycling policy спроектировать?
designsymfonyconcurrency - 25
Producers создают 1 200 jobs/s, но payment provider безопасно принимает только 800 calls/s. Как применить backpressure?
backpressure - 26
Laravel Octane application обслуживает 20 tenants через persistent workers. Как задать scope и reset для CurrentTenant?
laravelasync - 27
Symfony container содержит 9 000 services, а cache warmup занимает 75 секунд. Что проверить до отказа от autowiring?
symfonycontainerscaching - 28
Laravel API использует tenant resolution, authentication, rate limiting, transactions и response caching middleware. Какой порядок выбрать?
middlewarelaravelapi - 29
Laravel endpoint загружает 100 orders и выполняет 301 SQL query, потому что каждый order обращается к customer и items. Как исправить без overfetching?
sqlqueriesendpoints - 30
Doctrine import 100 000 entities занимает 14 минут и достигает 1,3 ГБ до завершения flush. Как изменить UnitOfWork pattern?
orm - 31
Symfony controller валидирует discount через attributes, но тот же invalid discount приходит через Messenger. Где должна жить rule?
validationsymfony - 32
Laravel model observer отправляет email внутри database transaction, добавляя 900 мс и отправляя письмо даже при rollback следующей write. Что изменить?
databasetransactionslaravel - 33
Symfony kernel listener запускается на каждом request, выполняет два database queries и нужен только для 8 admin routes. Как сузить scope?
databasequeriessymfony - 34
PDO query фильтрует tenant_id и status, сортирует по created_at и id, возвращает 50 rows, но сканирует 4 миллиона. Какой index проверить?
indexesqueriespdo - 35
Page 2 000 orders API использует LIMIT 50 OFFSET 99 950 и занимает 1,4 секунды. Как изменить pagination?
pagination - 36
Два PHP requests читают available credit 100 и каждый тратит 80 под READ COMMITTED. Какой database control применить?
databasephp - 37
PDO report принимает до 500 account IDs и сейчас конкатенирует их в IN clause. Как сохранить safety и efficiency?
pdo - 38
После создания order следующий GET иногда возвращает 404 с replica, отстающей на 800 мс. Как обеспечить read-after-write behavior?
replication - 39
Doctrine dashboard загружает 60 000 entities для расчёта пяти totals и занимает 3,8 секунды. Какую query shape использовать?
queriesorm - 40
Swoole service должен обслуживать 2 000 concurrent requests с database calls по 120 мс. Какой client и pool design выбрать?
designasyncdatabase - 41
ReactPHP websocket service должен сохранять responsiveness 10 000 connections, пока JSON export потребляет 700 мс CPU. Где выполнять export?
reactresponsivewebsockets - 42
Команда оборачивает blocking curl_exec в Fiber и ожидает concurrent execution 500 HTTP calls. Почему это не масштабируется?
reacthttpconcurrency - 43
Long-running Octane worker обработает 20 000 requests с чередованием tenants и locales. Какой state нужно сбрасывать на каждой boundary?
async - 44
Swoole application открывает одно database connection на coroutine, поэтому 800 concurrent requests исчерпывают PostgreSQL. Как рассчитать pool?
databasepostgresconcurrency - 45
POST /payments повторяется после timeout 10 секунд и иногда списывает дважды. Какой API contract добавить?
endpointsresilience - 46
Bulk API принимает 10 000 customer updates одним request и занимает FPM worker на 45 секунд. Как его перепроектировать?
api - 47
Три API возвращают validation failures в несовместимых shapes, заставляя clients писать route-specific parsers. Какой error contract стандартизировать?
validationapi - 48
GraphQL orders query запрашивает 200 orders с customer и items и создаёт 401 SQL query. Как его ограничить?
sqlqueriesgraphql - 49
Популярный Redis key истекает каждый час, и 600 PHP requests одновременно пересчитывают report за 2 секунды. Как остановить stampede?
redisphp - 50
Один Redis Cluster key получает 90 000 reads/s и насыщает один shard, пока пять остальных idle. Как изменить cache?
shardingrediscaching - 51
Laravel Octane workers начинают со 120 МБ RSS и достигают 900 МБ после 15 000 requests, хотя memory_get_usage показывает только 260 МБ. Как расследовать?
laravelasyncmemory - 52
Swoole service добавляет около 8 МБ RSS на 1 000 requests во всех 64 workers, а рост коррелирует со сменой tenants. Что проверить первым?
async - 53
Symfony Messenger worker растёт с 95 до 710 МБ после 10 000 jobs, а identity map Doctrine содержит 180 000 entities. Что изменить?
ormsymfony - 54
ReactPHP websocket process держит 12 000 connections, но RSS растёт на 300 МБ при отключении 2 000 clients. Как найти retained data?
reactwebsocketsconcurrency - 55
RSS PDF worker растёт со 140 МБ до 1,2 ГБ, но PHP heap остаётся около 170 МБ, а gc_collect_cycles ничего не меняет. Каков следующий шаг?
data-structuresphp - 56
Octane worker удерживает 40 копий request object после 40 запусков route, а memory graph ведёт через event-listener closures. Как убрать cycle?
closuresmemoryasync - 57
Production перезапускает queue workers каждые 500 jobs, скрывая leak 2 МБ на job, но restarts уже потребляют 18% CPU. Как сбалансировать mitigation и diagnosis?
data-structures - 58
Traffic вырос на 35%, PHP-FPM p99 вырос со 180 мс до 2,4 секунды, max_children достигнут, а listen queue равна 320. Что проверить первым?
data-structuresphpphp-fpm - 59
PHP-FPM host начинает swapping после увеличения pm.max_children с 60 до 110, а p99 latency растёт до 6 секунд. Как восстановить?
zero-to-onelatencyphp-fpm - 60
Deploy удваивает PHP-FPM replicas с 20 до 40, и PostgreSQL сразу достигает limit 800 connections. Как сдержать и исправить fan-out?
postgresreplicationfan-out - 61
External tax API замедляется со 120 мс до 4 секунд, удерживая 90% FPM workers и блокируя unrelated catalog requests. Что делать?
api - 62
CPU достигает 100% на всех FPM hosts после изменения payload, при нормальной latency database и Redis. P99 одного endpoint вырос до 9 секунд. Как локализовать?
databaseredisendpoints - 63
Autoscaling добавляет 30 PHP pods во время flash sale, но p99 всё равно растёт с 250 мс до 3 секунд, а database CPU достигает 96%. Каково решение?
databasescalingphp - 64
Queue backlog растёт с 5 000 до 900 000 jobs за 40 минут при 95% занятости workers. Как выбрать между scaling и throttling?
backlogscalingdata-structures - 65
После serializer release database QPS растёт с 4 000 до 28 000, checkout errors достигают 9%, а traces показывают новый nested relation query на каждый item. Как действовать?
databasequeriessoft-skills - 66
Быстрый N+1 fix eager-load шесть relations для 500 products, сокращает queries с 3 001 до 7, но увеличивает memory со 180 МБ до 1,4 ГБ. Что изменить?
n+1queriesmemory - 67
PostgreSQL settlement query замедляется со 180 мс до 6,5 секунды и пишет 4 ГБ temporary files на call после утроения result volume. Как отреагировать?
queriespostgres - 68
MySQL query внезапно выбирает неправильный index после роста одного tenant с 1 до 40 миллионов rows, хотя SQL не менялся. Что проверить?
sqlindexesqueries - 69
UPDATE по primary key занимает 12 секунд несмотря на index, а database monitoring показывает lock waits. Как диагностировать?
databaseindexesprimary-keys - 70
Новый customer search разрешает двухсимвольные `%term%` matches по 80 миллионам rows, насыщает read replica и увеличивает API p99 до 11 секунд. Что делать?
replicationapi - 71
SQL injection подтверждена в report endpoint, который конкатенирует sort и filter values, а logs показывают 37 suspicious requests. Что сделать первым?
sqlendpointsinjection - 72
Stored XSS payload появляется в 4 200 support tickets после использования raw output в Blade template. Как сдержать и исправить?
templatingxss - 73
В течение 12-часового exposure window public endpoint вызывает unserialize для signed cookie, а leaked signing key делает возможным gadget-chain attack. Как отреагировать?
cookiesendpoints - 74
Image-import feature может получать arbitrary URLs, а audit logs показывают 9 requests к cloud metadata address. Как закрыть SSRF path?
- 75
Laravel debug page раскрыла database и API credentials 260 authenticated users в течение 18 минут. Как отреагировать?
databaseapilaravel - 76
Tenant получает invoice другого tenant, меняя /invoices/781 на /invoices/782, а logs показывают 64 cross-tenant reads. Как исправить authorization model?
auth - 77
Composer audit сообщает critical remote-code-execution vulnerability в package, загружаемом 35 PHP services. Как координировать технический response?
vulnerabilitiescomposerphp - 78
Cache lock имеет TTL 1 секунду, recomputation занимает 4 секунды, и один expiry запускает семь refreshers, чьи late results перезаписывают новые data. Как исправить incident?
incidentscaching - 79
Deploy invalidates 200 000 product keys одновременно, снижает Redis hit rate с 96% до 8% и насыщает PostgreSQL. Как восстановить?
postgresredisdeployment - 80
Удаление одного Redis value размером 180 МБ блокирует shard на 1,7 секунды каждые пять минут и вызывает timeout unrelated sessions. Как диагностировать и убрать large-key hazard?
shardingredissessions - 81
Два requests получают cache miss, вычисляют versions 41 и 42, затем медленная version 41 перезаписывает 42 на десять минут. Как предотвратить stale fill race?
caching - 82
Redis недоступен шесть минут, и automatic cache fallback увеличивает PostgreSQL connections со 180 до 790 из 800. Что делать?
postgresrediscaching - 83
Response cache не включает tenant ID в key и отдаёт 17 invoices неправильным tenants. Как сдержать и исправить cache design?
designcaching - 84
После deployment 120 из 240 FPM workers вызывают новый method, а остальные падают с undefined method из-за old class в OPcache. Как восстановить?
opcacherestdeployment - 85
Rollback возвращает old files, но 24 workers с новым OPcache preload продолжают падать. Чего не хватает rollback?
schedulingrollbackopcache - 86
Release содержит новый application code, но old vendor directory на 12 из 80 hosts вызывает class-not-found errors. Как исправить artifact pipeline?
ci-cdartifactsprocurement - 87
Rolling deploy оставляет 30% queue workers на old message class и 70% на new schema, вызывая deserialization failures. Как вернуть compatibility?
schemadeploymentdata-structures - 88
Новый Laravel release читает column до завершения migration на всех database shards, вызывая 500 errors у 18% tenants. Что откатывать?
databasemigrationssharding - 89
Production release на 60 instances продолжает использовать вчерашние Laravel config и routes, хотя files правильные. Как диагностировать stale caches?
laravelcachingconfig - 90
PHP 5.6 monolith содержит 1,2 миллиона lines, 240 Composer packages и лишь 18% test coverage. Как спланировать первый stage migration на PHP 8?
migrationsmonolithcoverage - 91
Прямой test PHP 5.6 to 8.3 создаёт 14 000 failures из-за language changes и dependencies. Как уменьшить change surface?
dependenciesphp - 92
Первый service, выделенный из monolith, пишет customer data в обе databases, и 0,6% records уже расходятся. Как вернуть один authority?
databasemonolith - 93
Symfony major upgrade затрагивает 160 bundles, queue serialization, security rules и 900 routes. Как провести stages без остановки delivery?
serializationsymfonydata-structures - 94
Добавление declare(strict_types=1) в 3 000 legacy files меняет numeric-string behavior в payment inputs. Как безопасно мигрировать?
- 95
Nightly PHP cron обрабатывает 4 миллиона rows шесть часов, пересекается со следующим run и не умеет resume после failure. Как перенести его в workers?
concurrencyphpcron - 96
Homegrown PHP authentication module нужно заменить, но 3 миллиона active sessions используют его cookie format. Какой migration path выбрать?
authsessionscookies - 97
Junior engineer исправляет mixed-code deploys отключением OPcache на всех 80 hosts, увеличивая CPU на 45%. Как провести его через correction?
mentoringdeploymentopcache - 98
Middle engineer предлагает увеличить pm.max_children с 70 до 180 для исправления p99 2 секунды, но database имеет лишь 120 spare connections. Как review решение?
zero-to-onedatabase - 99
Engineer закрывает 3 SQL injection payloads запретом quotes через regex, но endpoint продолжает concatenation sort и filter input. Как направить fix?
sqlendpointsinjection - 100
Engineer скрывает endpoint с 101 query за Redis cache на 30 минут, но stale prices вызывают 2% checkout corrections. Как направить redesign?
queriesredisendpoints