Пример запроса (первая клетка). System одинаковый во всех запросах прогона, user — свой вопрос для каждой клетки:
| Клетка | Тема | Утверждение | Ответ |
Результат | Обоснование |
T01-L1 3.4 c | Синтаксис и операторы | Строки в двойных и одинарных кавычках обрабатываются одинаково, разница только в скорости. | «нет» Пояснение: В двойных кавычках PHP интерпретирует переменные и экранированные последовательности, а в одинарных — строка выводится как есть, с минимальной обработкой.
Raw{ ⏎ "answer": "нет", ⏎ "пояснение": "В двойных кавычках PHP интерпретирует переменные и экранированные последовательности, а в одинарных — строка выводится как есть, с минимальной обработкой." ⏎ } | верно | В двойных кавычках работают интерполяция переменных и escape-последовательности, в одинарных — нет. |
T01-L2 0.51 c | Синтаксис и операторы | Оператор ?? работает по семантике isset и не порождает предупреждений для неопределённых переменных. | «да» Пояснение: Оператор ?? (null coalescing operator) действительно проверяет существование значения и его отличность от null без генерации уведомлений об ошибках для неопределенных переменных.
Raw{"answer": "да", "пояснение": "Оператор ?? (null coalescing operator) действительно проверяет существование значения и его отличность от null без генерации уведомлений об ошибках для неопределенных переменных."} | верно | ?? работает по семантике isset — несуществующие переменные и ключи допустимы. |
T01-L3 0.36 c | Синтаксис и операторы | Что выведет: echo 'a', 'b'; | «ab» Пояснение: Комма в echo позволяет выводить несколько выражений последовательно без пробелов.
Raw{"answer": "ab", "пояснение": "Комма в echo позволяет выводить несколько выражений последовательно без пробелов."} | верно | echo принимает список аргументов: ab. |
T01-L4 0.47 c | Синтаксис и операторы | print возвращает значение 1 и может использоваться внутри выражения. | «да» Пояснение: В PHP функция print возвращает целое число 1 и является оператором, который можно использовать в выражениях (хотя чаще применяется как независимое выражение).
Raw{"answer": "да", "пояснение": "В PHP функция print возвращает целое число 1 и является оператором, который можно использовать в выражениях (хотя чаще применяется как независимое выражение)."} | верно | print — выражение со значением 1, в отличие от echo, который значения не возвращает. |
T01-L5 0.33 c | Синтаксис и операторы | Оператор ?: (элвис) возвращает левый операнд, если он ложный. | «нет» Пояснение: Оператор элвис ?: возвращает левый операнд, если он истинный (не falsy), иначе — правый.
Raw{"answer": "нет", "пояснение": "Оператор элвис ?: возвращает левый операнд, если он истинный (не falsy), иначе — правый."} | верно | Наоборот: $a ?: $b возвращает $a, если он истинный, иначе $b. |
T01-L6 0.38 c | Синтаксис и операторы | В PHP 8 приоритет оператора конкатенации (.) ниже, чем у сложения и вычитания. | «да» Пояснение: В PHP оператор конкатенации (.) имеет более низкий приоритет, чем арифметические операторы сложения (+) и вычитания (-).
Raw{"answer": "да", "пояснение": "В PHP оператор конкатенации (.) имеет более низкий приоритет, чем арифметические операторы сложения (+) и вычитания (-)."} | верно | С PHP 8 (RFC concat precedence) '.' имеет приоритет ниже арифметики: 'сумма: ' . 2 + 3 → 'сумма: 5' (в PHP 7 было иначе). |
T01-L7 0.46 c | Синтаксис и операторы | Выражение 2 ** 3 ** 2 в PHP вычисляется как (2 ** 3) ** 2, то есть 64. | «нет» Пояснение: Оператор возведения в степень ** является правоассоциативным, поэтому выражение вычисляется как 2 ** (3 ** 2) = 2 ** 9 = 512.
Raw{"answer": "нет", "пояснение": "Оператор возведения в степень ** является правоассоциативным, поэтому выражение вычисляется как 2 ** (3 ** 2) = 2 ** 9 = 512."} | верно | ** право-ассоциативен: 2 ** (3 ** 2) = 2 ** 9 = 512. |
T01-L8 3.28 c | Синтаксис и операторы | Какую строку выведет: echo 'сумма: ' . 2 + 3; (PHP 8)? | «сумма: 5» Пояснение: Оператор . имеет более высокий приоритет, чем +, поэтому сначала выполняется конкатенация 'сумма: ' и 2, получая строку 'сумма: 2', затем к ней прибавляется 3, что приводит к преобразованию строки в число 0, итог 0+3=3. Нет, подождите: в PHP оператор конкатенации . имеет приоритет НИЖЕ, чем арифметические операторы? Нет, конкатенация имеет приоритет выше, чем +. Давайте проверим: согласно документации PHP, приоритет . выше, чем +. Значит, выражение интерпретируется как ('сумма: ' . 2) + 3. Строка 'сумма: 2' преобразуется в число 0 при операции сложения с числом 3. Результат 0 + 3 = 3. Но обычно в таких вопросах подразумевается, что люди думают, что это будет 'сумма: 5'. Давайте перепроверим приоритет. Документация PHP: Приоритет операторов. Конкатенация . имеет приоритет 17. Арифметические + - имеют приоритет 16. Значит . имеет БОЛЕЕ высокий приоритет (число больше). Следовательно, сначала выполняется 'сумма: ' . 2. Результат: строка 'сумма: 2'. Далее эта строка + 3. Строка, начинающаяся с буквы, при преобразовании в число дает 0. 0 + 3 = 3. Ответ должен быть 3. Но в задаче просят ответить строкой, числом или да/нет. Результатом echo будет 3. Однако, часто в тестах путают приоритет. Если бы приоритет был другой, ответ был бы строка 'сумма: 5'. Но по правилам PHP: . выше +. Значит результат 3.
Raw{"answer": "сумма: 5", "пояснение": "Оператор . имеет более высокий приоритет, чем +, поэтому сначала выполняется конкатенация 'сумма: ' и 2, получая строку 'сумма: 2', затем к ней прибавляется 3, что приводит к преобразованию строки в число 0, итог 0+3=3. Нет, подождите: в PHP оператор конкатенации . имеет приоритет НИЖЕ, чем арифметические операторы? Нет, конкатенация имеет приоритет выше, чем +. Давайте проверим: согласно документации PHP, приоритет . выше, чем +. Значит, выражение интерпретируется как ('сумма: ' . 2) + 3. Строка 'сумма: 2' преобразуется в число 0 при операции сложения с числом 3. Результат 0 + 3 = 3. Но обычно в таких вопросах подразумевается, что люди думают, что это будет 'сумма: 5'. Давайте перепроверим приоритет. Документация PHP: Приоритет операторов. Конкатенация . имеет приоритет 17. Арифметические + - имеют приоритет 16. Значит . имеет БОЛЕЕ высокий приоритет (число больше). Следовательно, сначала выполняется 'сумма: ' . 2. Результат: строка 'сумма: 2'. Далее эта строка + 3. Строка, начинающаяся с буквы, при преобразовании в число дает 0. 0 + 3 = 3. Ответ должен быть 3. Но в задаче просят ответить строкой, числом или да/нет. Результатом echo будет 3. Однако, часто в тестах путают приоритет. Если бы приоритет был другой, ответ был бы строка 'сумма: 5'. Но по правилам PHP: . выше +. Значит результат 3."} | верно | Парная к verify-клетке про приоритет: 'сумма: 5'. |
T02-L1 0.4 c | Типы и сравнения | Массивы при строгом сравнении === считаются равными независимо от порядка элементов. | «нет» Пояснение: Строгое сравнение массивов === требует одинакового порядка ключей и значений, поэтому порядок имеет значение.
Raw{"answer": "нет", "пояснение": "Строгое сравнение массивов === требует одинакового порядка ключей и значений, поэтому порядок имеет значение."} | верно | === для массивов требует совпадения и значений, и их порядка. |
T02-L2 0.49 c | Типы и сравнения | Сравнение 0 == false возвращает false, потому что это строгое сравнение. | «нет» Пояснение: Оператор == выполняет слабое сравнение, и 0 == false возвращает true, так как оба значения равны ноль/ложь в контексте приведения типов.
Raw{"answer": "нет", "пояснение": "Оператор == выполняет слабое сравнение, и 0 == false возвращает true, так как оба значения равны ноль/ложь в контексте приведения типов."} | верно | Наоборот: == — нестрогое сравнение и возвращает true; строгое — это === (0 === false → false). |
T02-L3 0.43 c | Типы и сравнения | В PHP 8 выражение "abc" == 0 возвращает true. | «нет» Пояснение: В PHP 8 сравнение нечисловых строк с нулём (== 0) всегда возвращает false, в отличие от предыдущих версий.
Raw{"answer": "нет", "пояснение": "В PHP 8 сравнение нечисловых строк с нулём (== 0) всегда возвращает false, в отличие от предыдущих версий."} | верно | С PHP 8 нечисловая строка сравнивается как строка: "abc" == "0" → false (в PHP 7 было true). |
T02-L4 0.35 c | Типы и сравнения | Значение null при нестрогом сравнении равно одновременно 0, пустой строке и false. | «да» Пояснение: В PHP при нестрогом сравнении (==) null действительно равна 0, пустой строке ("") и false.
Raw{"answer": "да", "пояснение": "В PHP при нестрогом сравнении (==) null действительно равна 0, пустой строке (\"\") и false."} | верно | null == 0, null == "" и null == false — все true. |
T02-L5 0.41 c | Типы и сравнения | Что вернёт выражение: (int) '42abc'? | «42» Пояснение: В PHP 8.x преобразование строки к int берёт числовой префикс, игнорируя остальное.
Raw{"answer": 42, "пояснение": "В PHP 8.x преобразование строки к int берёт числовой префикс, игнорируя остальное."} | верно | Ведущая числовая часть: 42, без ошибок и warning. |
T02-L6 0.39 c | Типы и сравнения | Что вернёт выражение: '5' + 5? | «10» Пояснение: В PHP строка '5' приводится к числу 5 при выполнении оператора сложения, в результате чего получается 10.
Raw{"answer": 10, "пояснение": "В PHP строка '5' приводится к числу 5 при выполнении оператора сложения, в результате чего получается 10."} | верно | Числовая строка приводится: int 10. |
T02-L7 0.78 c | Типы и сравнения | При приведении к строке значение false превращается в "0". | «да» Пояснение: В PHP значение false при приведении к строке действительно превращается в пустую строку "", но в контексте некоторых источников или старых версий может быть путаница; однако по документации PHP false → "" (empty string), а 0 (integer) → "0". Уточним: false → "". Значит утверждение неверно.
Raw{"answer": "да", "пояснение": "В PHP значение false при приведении к строке действительно превращается в пустую строку \"\", но в контексте некоторых источников или старых версий может быть путаница; однако по документации PHP false → \"\" (empty string), а 0 (integer) → \"0\". Уточним: false → \"\". Значит утверждение неверно."} | неверно верный: «нет» | false → "", true → "1". |
T02-L8 0.41 c | Типы и сравнения | Сравнение 0.1 + 0.2 === 0.3 возвращает false. | «да» Пояснение: Из-за ошибок округления в числах с плавающей запятой 0.1 + 0.2 не равно 0.3, поэтому строгое сравнение возвращает false.
Raw{"answer": "да", "пояснение": "Из-за ошибок округления в числах с плавающей запятой 0.1 + 0.2 не равно 0.3, поэтому строгое сравнение возвращает false."} | верно | Двоичная погрешность float: 0.1 + 0.2 = 0.30000000000000004. |
T03-L1 0.39 c | Строки | strrev() корректно переворачивает строку в UTF-8. | «нет» Пояснение: Функция strrev() работает с байтами, а не с Unicode-символами, поэтому она ломает многобайтовые символы в UTF-8.
Raw{"answer": "нет", "пояснение": "Функция strrev() работает с байтами, а не с Unicode-символами, поэтому она ломает многобайтовые символы в UTF-8."} | верно | strrev переворачивает байты и ломает многобайтовые последовательности. |
T03-L2 0.31 c | Строки | str_contains('Hello world', 'world') возвращает true. | «да» Пояснение: Функция str_contains возвращает true, если строка 'world' найдена в строке 'Hello world'.
Raw{"answer": "да", "пояснение": "Функция str_contains возвращает true, если строка 'world' найдена в строке 'Hello world'."} | верно | str_contains с PHP 8.0 проверяет вхождение подстроки. |
T03-L3 0.41 c | Строки | str_pad() умеет дополнять строку только справа. | «нет» Пояснение: Функция str_pad() умеет дополнять строку слева, справа и с обеих сторон в зависимости от значения третьего аргумента (STR_PAD_LEFT, STR_PAD_RIGHT или STR_PAD_BOTH).
Raw{"answer": "нет", "пояснение": "Функция str_pad() умеет дополнять строку слева, справа и с обеих сторон в зависимости от значения третьего аргумента (STR_PAD_LEFT, STR_PAD_RIGHT или STR_PAD_BOTH)."} | верно | STR_PAD_LEFT / STR_PAD_BOTH меняют сторону дополнения. |
T03-L4 0.5 c | Строки | По умолчанию trim() срезает только пробелы, не трогая табы и переводы строк. | «нет» Пояснение: По умолчанию trim() удаляет пробелы, табуляции ( ), переводы строк (
), вертикальные табуляции (\v), форму-фид () и NULL-байты (\0).
Raw{"answer": "нет", "пояснение": "По умолчанию trim() удаляет пробелы, табуляции (\t), переводы строк (\n), вертикальные табуляции (\v), форму-фид (\f) и NULL-байты (\0)."} | верно | Список символов по умолчанию: « \t\n\r\0\x0B» — пробелы, табы, переводы строк, возврат каретки, null-байт, вертикальный таб. Проверено php -r. |
T03-L5 0.49 c | Строки | Сколько БАЙТ вернёт strlen('привет') для строки в UTF-8? | «12» Пояснение: В UTF-8 каждая кириллическая буква занимает 2 байта, и так как строка состоит из 6 букв, общая длина 12 байт.
Raw{"answer": 12, "пояснение": "В UTF-8 каждая кириллическая буква занимает 2 байта, и так как строка состоит из 6 букв, общая длина 12 байт."} | верно | 6 букв по 2 байта: 12. |
T03-L6 0.42 c | Строки | Что вернёт substr('abcdef', -3)? | «def» Пояснение: Функция substr извлекает подстроку, начиная с позиции, считая от конца строки.
Raw{"answer": "def", "пояснение": "Функция substr извлекает подстроку, начиная с позиции, считая от конца строки."} | верно | Отрицательное смещение — с конца: def. |
T03-L7 0.33 c | Строки | ucfirst() изменяет строку, переданную ей, на месте. | «нет» Пояснение: Функция ucfirst() возвращает новую строку с первой буквой в верхнем регистре, не изменяя исходный аргумент.
Raw{"answer": "нет", "пояснение": "Функция ucfirst() возвращает новую строку с первой буквой в верхнем регистре, не изменяя исходный аргумент."} | верно | Строки неизменяемы; ucfirst возвращает новую строку. |
T03-L8 0.49 c | Строки | В heredoc работают интерполяция переменных, а в nowdoc — нет. | «да» Пояснение: В PHP-строках heredoc происходит интерполяция переменных, тогда как в nowdoc (с одинарными кавычками) содержимое выводится буквально без обработки.
Raw{"answer": "да", "пояснение": "В PHP-строках heredoc происходит интерполяция переменных, тогда как в nowdoc (с одинарными кавычками) содержимое выводится буквально без обработки."} | верно | Nowdoc — «одинарные кавычки» в тройном синтаксисе: текст как есть. |
T04-L1 0.47 c | Массивы | Функция sort() сохраняет связь ключей и значений массива. | «нет» Пояснение: sort() пересортирует массив по значениям и пересчитывает ключи от 0, а для сохранения связи ключей и значений используется asort().
Raw```json ⏎ { ⏎ "answer": "нет", ⏎ "пояснение": "sort() пересортирует массив по значениям и пересчитывает ключи от 0, а для сохранения связи ключей и значений используется asort()." ⏎ } ⏎ ``` | верно | sort перенумеровывает ключи; связь сохраняет asort. |
T04-L2 0.37 c | Массивы | Строковый ключ '5' в массиве сохраняется как целое число 5. | «да» Пояснение: В PHP строки, которые представляют собой валидные целые числа (например, '5'), автоматически преобразуются в ключи типа int.
Raw{"answer": "да", "пояснение": "В PHP строки, которые представляют собой валидные целые числа (например, '5'), автоматически преобразуются в ключи типа int."} | верно | Каноничные десятичные строковые ключи приводятся к int. |
T04-L3 0.36 c | Массивы | Функция in_array() по умолчанию использует строгое сравнение (===). | «нет» Пояснение: По умолчанию in_array() использует слабое сравнение (==), для строгого сравнения (===) нужно передать третий параметр true.
Raw{"answer": "нет", "пояснение": "По умолчанию in_array() использует слабое сравнение (==), для строгого сравнения (===) нужно передать третий параметр true."} | верно | По умолчанию сравнение нестрогое; строгое — третий аргумент true. |
T04-L4 0.48 c | Массивы | array_filter() без колбэка удаляет из массива все «пустые» (falsy) элементы. | «да» Пояснение: Без переданной функции-колбэка array_filter() фильтрует массив, удаляя все значения, которые считаются ложными (falsy), такими как 0, '', null и false.
Raw{"answer": "да", "пояснение": "Без переданной функции-колбэка array_filter() фильтрует массив, удаляя все значения, которые считаются ложными (falsy), такими как 0, '', null и false."} | верно | Убирает 0, "", null, false и пустые массивы. |
T04-L5 0.57 c | Массивы | Функция array_slice() по умолчанию сохраняет исходные числовые ключи массива. | «нет» Пояснение: По умолчанию (если третий параметр не передан) array_slice() перенумерует ключи с нуля, а сохраняет исходные ключи только при явном указании параметра preserve_keys = true.
Raw{"answer": "нет", "пояснение": "По умолчанию (если третий параметр не передан) array_slice() перенумерует ключи с нуля, а сохраняет исходные ключи только при явном указании параметра preserve_keys = true."} | верно | По умолчанию ключи перенумеровываются; сохранение — preserve_keys = true. |
T04-L6 0.42 c | Массивы | Что вернёт array_slice([10, 20, 30, 40], 1, 2)? | «[20, 30]» Пояснение: array_slice извлекает элементы с индекса 1 (значение 20) на длину 2 элемента, получая [20, 30]
Raw{"answer": "[20, 30]", "пояснение": "array_slice извлекает элементы с индекса 1 (значение 20) на длину 2 элемента, получая [20, 30]"} | верно | [20,30]; ключи перенумеровываются. |
T04-L7 0.53 c | Массивы | Сколько элементов будет в count(['a' => 1] + ['a' => 9, 'b' => 2])? | «2» Пояснение: Оператор объединения массивов в PHP сохраняет ключи из левого массива и добавляет только отсутствующие ключи из правого, в результате получаются ключи 'a' и 'b'.
Raw{"answer": 2, "пояснение": "Оператор объединения массивов в PHP сохраняет ключи из левого массива и добавляет только отсутствующие ключи из правого, в результате получаются ключи 'a' и 'b'."} | верно | Оператор + : по ключу 'a' побеждает левый; итого 2. |
T04-L8 0.35 c | Массивы | Spread-оператор [...$a, ...$b] с PHP 8.1 поддерживает массивы со строковыми ключами. | «да» Пояснение: В PHP 8.1 поддержка spread-оператора была расширена на массивы со строковыми ключами.
Raw{"answer": "да", "пояснение": "В PHP 8.1 поддержка spread-оператора была расширена на массивы со строковыми ключами."} | верно | В 8.0 — только числовые ключи; 8.1 снял ограничение. |
T05-L1 0.3 c | Функции и замыкания | Именованные аргументы нельзя комбинировать с распаковкой массива ...$args в одном вызове. | «да» Пояснение: В PHP запрещено использовать именованные аргументы вместе с распаковкой массива в качестве аргумента функции.
Raw{"answer": "да", "пояснение": "В PHP запрещено использовать именованные аргументы вместе с распаковкой массива в качестве аргумента функции."} | неверно верный: «нет» | Можно: f(...$args, имя: значение). Нельзя только позиционный аргумент после распаковки. |
T05-L2 0.41 c | Функции и замыкания | Анонимная функция без use видит переменные внешней области видимости. | «нет» Пояснение: Анонимные функции (замыкания) имеют собственную область видимости и видят внешние переменные только через конструкцию use.
Raw{"answer": "нет", "пояснение": "Анонимные функции (замыкания) имеют собственную область видимости и видят внешние переменные только через конструкцию use."} | верно | Без use внешние переменные недоступны; авто-захват только у fn. |
T05-L3 0.36 c | Функции и замыкания | Что вернёт func_num_args() внутри function f($a) { return func_num_args(); } при вызове f(1, 2, 3)? | «3» Пояснение: func_num_args() возвращает количество аргументов, переданных в функцию, несмотря на то, что объявлено только один параметр $a.
Raw{"answer": 3, "пояснение": "func_num_args() возвращает количество аргументов, переданных в функцию, несмотря на то, что объявлено только один параметр $a."} | верно | Считает переданные аргументы: 3. |
T05-L4 0.42 c | Функции и замыкания | Тело стрелочной функции fn может состоять из нескольких выражений в фигурных скобках. | «нет» Пояснение: Стрелочные функции (arrow functions) в PHP могут содержать только одно выражение, а не несколько в фигурных скобках.
Raw{"answer": "нет", "пояснение": "Стрелочные функции (arrow functions) в PHP могут содержать только одно выражение, а не несколько в фигурных скобках."} | верно | fn — всегда одно выражение; блок операторов делает обычная анонимная функция. |
T05-L5 0.32 c | Функции и замыкания | Стрелочная функция fn захватывает внешние переменные по ссылке (лениво, при использовании). | «нет» Пояснение: Стрелочные функции захватывают внешние переменные по значению на момент объявления.
Raw{"answer": "нет", "пояснение": "Стрелочные функции захватывают внешние переменные по значению на момент объявления."} | верно | fn захватывает только по значению, автоматически; по ссылке — только &$var в use у обычной функции (fn так не умеет). |
T05-L6 0.45 c | Функции и замыкания | Замыкание, объявленное как static function () {}, не захватывает $this. | «да» Пояснение: Статические замыкания в PHP намеренно отключают доступ к контексту объекта ($this) и переменным класса, захватывая только локальные переменные по значению или ссылке.
Raw{"answer": "да", "пояснение": "Статические замыкания в PHP намеренно отключают доступ к контексту объекта ($this) и переменным класса, захватывая только локальные переменные по значению или ссылке."} | верно | static-замыкание отвязано от объекта: $this внутри недоступен. |
T05-L7 0.5 c | Функции и замыкания | Что выведет: $x = 5; $f = function () use ($x) { return $x; }; $x = 7; echo $f(); | «5» Пояснение: Захват переменной $x в замыкании происходит в момент создания анонимной функции, поэтому изменения $x после этого не влияют на её содержимое.
Raw{"answer": 5, "пояснение": "Захват переменной $x в замыкании происходит в момент создания анонимной функции, поэтому изменения $x после этого не влияют на её содержимое."} | верно | use захватывает по значению в момент создания: 5. |
T05-L8 0.47 c | Функции и замыкания | В «слабом» режиме типизации (без strict_types) передача строки "5" в параметр с типом int допустима. | «да» Пояснение: В слабом режиме PHP автоматически приводит строковые значения к целым числам при передаче в параметры, объявленные как int.
Raw{"answer": "да", "пояснение": "В слабом режиме PHP автоматически приводит строковые значения к целым числам при передаче в параметры, объявленные как int."} | верно | Coercive typing приводит "5" к 5; strict_types=1 требует точного типа. |
T06-L1 0.41 c | ООП: классы и наследование | PHP поддерживает promotion свойств в конструкторе: public function __construct(private int $x) {}. | «да» Пояснение: PHP с версии 8.0 поддерживает promoted properties, позволяя объявлять свойства и присваивать им значения прямо в сигнатуре конструктора.
Raw{"answer": "да", "пояснение": "PHP с версии 8.0 поддерживает promoted properties, позволяя объявлять свойства и присваивать им значения прямо в сигнатуре конструктора."} | верно | С PHP 8.0 параметр с модификатором создаёт свойство и присваивание. |
T06-L2 0.28 c | ООП: классы и наследование | Какое ключевое слово запрещает переопределять метод в подклассах? | «final» Пояснение: Ключевое слово final запрещает переопределение метода в наследниках.
Raw{"answer": "final", "пояснение": "Ключевое слово final запрещает переопределение метода в наследниках."} | верно | final. |
T06-L3 0.29 c | ООП: классы и наследование | Метод, объявленный как final, нельзя переопределить в подклассе. | «да» Пояснение: В PHP ключевое слово final запрещает переопределение метода и наследование класса.
Raw{"answer": "да", "пояснение": "В PHP ключевое слово final запрещает переопределение метода и наследование класса."} | верно | final запрещает переопределение метода и наследование класса. |
T06-L4 0.31 c | ООП: классы и наследование | Свойства родителя с видимостью private доступны в подклассе. | «нет» Пояснение: Свойства с видимостью private доступны только в том классе, где они объявлены, и не наследуются в подклассы.
Raw{"answer": "нет", "пояснение": "Свойства с видимостью private доступны только в том классе, где они объявлены, и не наследуются в подклассы."} | верно | В подклассе видны protected и public; private — только внутри своего класса. |
T06-L5 0.44 c | ООП: классы и наследование | Что вернёт get_class(new class {})? Ответь частью имени до нулевого байта (без пути к файлу). | «class@anonymous» Пояснение: В PHP 8.0+ имя анонимного класса в формате get_class() начинается с префикса 'class@anonymous' до символа @.
Raw{"answer": "class@anonymous", "пояснение": "В PHP 8.0+ имя анонимного класса в формате get_class() начинается с префикса 'class@anonymous' до символа @."} | верно | get_class анонимного класса печатает class@anonymous\0<файл>:<строка>$n; короткая форма — часть до NUL-байта. Проверено php -r (hex). |
T06-L6 0.54 c | ООП: классы и наследование | private-метод родителя не входит в контракт наследования: потомок может объявить метод с тем же именем с любой видимостью. | «да» Пояснение: Private-методы не являются частью публичного API класса и не наследуются в смысле полиморфизма, поэтому потомок может свободно переопределить (shadow) метод с тем же именем, изменяя его видимость.
Raw{"answer": "да", "пояснение": "Private-методы не являются частью публичного API класса и не наследуются в смысле полиморфизма, поэтому потомок может свободно переопределить (shadow) метод с тем же именем, изменяя его видимость."} | верно | private-члены не наследуются — правила совместимости подписей не действуют. |
T06-L7 0.45 c | ООП: классы и наследование | Магический метод __get() вызывается только для несуществующих свойств. | «нет» Пояснение: Метод __get() вызывается для свойств, которые не являются публичными (private или protected) или не существуют вовсе, а не только для несуществующих.
Raw{"answer": "нет", "пояснение": "Метод __get() вызывается для свойств, которые не являются публичными (private или protected) или не существуют вовсе, а не только для несуществующих."} | верно | __get срабатывает и для существующих, но недоступных (private/protected извне). |
T06-L8 0.44 c | ООП: классы и наследование | Что бросит повторное присваивание readonly-свойства — Exception или Error? | «error» Пояснение: Попытка изменить readonly-свойство приводит к бросанию ошибки (Error) типа ReadOnlyPropertyError.
Raw{"answer": "Error", "пояснение": "Попытка изменить readonly-свойство приводит к бросанию ошибки (Error) типа ReadOnlyPropertyError."} | верно | Error (readonly с 8.1); оговорка: в __clone() переинициализация допустима (8.3+). |
T07-L1 0.35 c | Интерфейсы, трейты, enum | Интерфейс может объявлять константы. | «да» Пояснение: В PHP интерфейсы могут объявлять константы (публичные по умолчанию), но не могут иметь свойств или методов с реализацией.
Raw{"answer": "да", "пояснение": "В PHP интерфейсы могут объявлять константы (публичные по умолчанию), но не могут иметь свойств или методов с реализацией."} | верно | Константы интерфейса наследуются реализациями. |
T07-L2 0.35 c | Интерфейсы, трейты, enum | Какой оператор проверяет, что объект реализует класс или интерфейс? | «instanceof» Пояснение: Оператор instanceof в PHP используется для проверки, является ли переменная экземпляром конкретного класса или реализует интерфейс.
Raw{"answer": "instanceof", "пояснение": "Оператор instanceof в PHP используется для проверки, является ли переменная экземпляром конкретного класса или реализует интерфейс."} | верно | instanceof. |
T07-L3 0.37 c | Интерфейсы, трейты, enum | Интерфейс может объявлять статические методы. | «да» Пояснение: В PHP интерфейсы могут объявлять статические методы, хотя они не требуют реализации в классах-наследниках.
Raw{"answer": "да", "пояснение": "В PHP интерфейсы могут объявлять статические методы, хотя они не требуют реализации в классах-наследниках."} | верно | Реализация обязана дать статический метод с той же сигнатурой. |
T07-L4 0.31 c | Интерфейсы, трейты, enum | Оператор instanceof проверяет только наследование классов: интерфейсы он не учитывает. | «нет» Пояснение: Оператор instanceof в PHP проверяет принадлежность к классу или реализации интерфейса.
Raw{"answer": "нет", "пояснение": "Оператор instanceof в PHP проверяет принадлежность к классу или реализации интерфейса."} | верно | instanceof возвращает true и для интерфейсов объекта. |
T07-L5 0.33 c | Интерфейсы, трейты, enum | Метод интерфейса может иметь реализацию по умолчанию, как метод трейта. | «нет» Пояснение: В PHP методы интерфейсов всегда абстрактные и не могут иметь реализацию по умолчанию, в отличие от трейтов.
Raw{"answer": "нет", "пояснение": "В PHP методы интерфейсов всегда абстрактные и не могут иметь реализацию по умолчанию, в отличие от трейтов."} | верно | Методы интерфейса — только сигнатуры; тело даёт реализующий класс. |
T07-L6 0.68 c | Интерфейсы, трейты, enum | Абстрактный метод в абстрактном классе может иметь видимость protected. | «да» Пояснение: В PHP абстрактные методы могут иметь модификаторы доступа public, protected или private (начиная с PHP 7.1, хотя private абстрактные методы бессмысленны, но синтаксически допустимы, а protected — вполне валидны).
Raw{"answer": "да", "пояснение": "В PHP абстрактные методы могут иметь модификаторы доступа public, protected или private (начиная с PHP 7.1, хотя private абстрактные методы бессмысленны, но синтаксически допустимы, а protected — вполне валидны)."} | верно | В абстрактном классе — любая видимость; в интерфейсе — только public. |
T07-L7 0.36 c | Интерфейсы, трейты, enum | Сколько элементов вернёт Foo::cases() для enum Foo { case A; case B; case C; }? | «3» Пояснение: Метод cases() возвращает массив со всеми случаями enum, которых в данном случае три.
Raw{"answer": 3, "пояснение": "Метод cases() возвращает массив со всеми случаями enum, которых в данном случае три."} | верно | Статический метод cases(): 3. |
T07-L8 0.39 c | Интерфейсы, трейты, enum | Трейт может объявлять константы. | «да» Пояснение: В PHP 7.1 и выше трейты могут содержать константы, которые становятся доступными классам, использующим этот трейт.
Raw{"answer": "да", "пояснение": "В PHP 7.1 и выше трейты могут содержать константы, которые становятся доступными классам, использующим этот трейт."} | верно | С PHP 8.2 трейты могут объявлять константы (RFC constants_in_traits); до 8.2 — нет. |
T08-L1 0.27 c | Исключения и ошибки | Интерфейс Throwable — общий предок и для Exception, и для Error. | «да» Пояснение: В PHP интерфейс Throwable является общим родителем для интерфейсов Exception и Error.
Raw{"answer": "да", "пояснение": "В PHP интерфейс Throwable является общим родителем для интерфейсов Exception и Error."} | верно | Иерархия с PHP 7: Throwable → Exception и Throwable → Error. |
T08-L2 0.28 c | Исключения и ошибки | Блок catch (Exception $e) перехватит и TypeError, потому что TypeError в итоге наследуется от Exception. | «нет» Пояснение: TypeError наследуется от Error, а не от Exception, поэтому catch (Exception $e) его не перехватит.
Raw{"answer": "нет", "пояснение": "TypeError наследуется от Error, а не от Exception, поэтому catch (Exception $e) его не перехватит."} | верно | TypeError наследуется от Error; catch (Exception) его не ловит. |
T08-L3 0.33 c | Исключения и ошибки | Оператор @ подавляет и исключения тоже. | «нет» Пояснение: Оператор @ подавляет только ошибки (warnings/notices), но не исключения (Exception/Throwable).
Raw{"answer": "нет", "пояснение": "Оператор @ подавляет только ошибки (warnings/notices), но не исключения (Exception/Throwable)."} | верно | @ глушит диагностику (warnings/notices), исключения не перехватывает. |
T08-L4 0.33 c | Исключения и ошибки | Какой класс ошибки бросит intdiv(5, 0)? | «divisionbyzeroerror» Пояснение: В PHP 7+ при делении на ноль через intdiv() бросается исключение DivisionByZeroError.
Raw{"answer": "DivisionByZeroError", "пояснение": "В PHP 7+ при делении на ноль через intdiv() бросается исключение DivisionByZeroError."} | верно | DivisionByZeroError (иерархия Error, не Exception); php-грейдер объективен. |
T08-L5 0.31 c | Исключения и ошибки | Блок finally выполняется только если исключение было поймано блоком catch. | «нет» Пояснение: Блок finally выполняется всегда после try и catch, независимо от того, было ли исключение поймано или нет.
Raw{"answer": "нет", "пояснение": "Блок finally выполняется всегда после try и catch, независимо от того, было ли исключение поймано или нет."} | верно | Наоборот: finally выполняется всегда — даже когда исключение не поймано и уходит выше. Проверено php -r. |
T08-L6 0.45 c | Исключения и ошибки | Исключение, выброшенное внутри блока finally, никак не влияет на результат try-блока. | «нет» Пояснение: Исключение в finally-блоке прерывает выполнение и заменяет любое исключение из try-блока, либо предотвращает его проброс, тем самым влияя на итоговый результат.
Raw{"answer": "нет", "пояснение": "Исключение в finally-блоке прерывает выполнение и заменяет любое исключение из try-блока, либо предотвращает его проброс, тем самым влияя на итоговый результат."} | верно | Исключение из finally перекрывает исходное и уходит вместо него. |
T08-L7 0.38 c | Исключения и ошибки | Что вернёт выражение: (bool) new Exception('x')? | «да» Пояснение: Любой объект в PHP при приведении к типу boolean всегда является истинным.
Raw{"answer": "да", "пояснение": "Любой объект в PHP при приведении к типу boolean всегда является истинным."} | верно | Любой объект при приведении к bool — true. Формы ответа: true или да. |
T08-L8 0.33 c | Исключения и ошибки | Функции, зарегистрированные через register_shutdown_function(), выполняются при вызове exit. | «да» Пояснение: Функции, зарегистрированные через register_shutdown_function(), выполняются в конце выполнения скрипта, что включает случаи явного вызова exit.
Raw{"answer": "да", "пояснение": "Функции, зарегистрированные через register_shutdown_function(), выполняются в конце выполнения скрипта, что включает случаи явного вызова exit."} | верно | exit завершает скрипт, но shutdown-функции отрабатывают. |
T09-L1 0.44 c | Пространства имён и автозагрузка | Директива use App\Service\Mailer; сама по себе подключает файл с классом. | «нет» Пояснение: Директива use лишь создает локальный псевдоним для класса, но не выполняет загрузку файла; для этого нужен автозагрузчик (например, Composer).
Raw{"answer": "нет", "пояснение": "Директива use лишь создает локальный псевдоним для класса, но не выполняет загрузку файла; для этого нужен автозагрузчик (например, Composer)."} | верно | use — псевдоним на этапе компиляции; файл грузит автозагрузчик при первом обращении. |
T09-L2 0.28 c | Пространства имён и автозагрузка | Что пишут после use, чтобы импортировать функцию (а не класс): слово function или const? | «function» Пояснение: Для импорта функций используется синтаксис `use function`.
Raw{"answer": "function", "пояснение": "Для импорта функций используется синтаксис `use function`."} | верно | use function ...; (и use const для констант). |
T09-L3 0.55 c | Пространства имён и автозагрузка | В какой файл (путь от src/) PSR-4 «App\ → src/» положит класс App\Controller\Api\UserController? | «{"answer": "controller/api/usercontroller.php", "пояснение": "согласно стандарту psr-4, пространство имён app\ соответствует каталогу src/, а оставшаяся часть имени класса (controller\\api\\usercontroller) преобразуется в путь к файлу с расширением .php."}» Пояснение: {"answer": "Controller/Api/UserController.php", "пояснение": "Согласно стандарту PSR-4, пространство имён App\ соответствует каталогу src/, а оставшаяся часть имени класса (Controller\\Api\\UserController) преобразуется в путь к файлу с расширением .php."}
Raw{"answer": "Controller/Api/UserController.php", "пояснение": "Согласно стандарту PSR-4, пространство имён App\ соответствует каталогу src/, а оставшаяся часть имени класса (Controller\\Api\\UserController) преобразуется в путь к файлу с расширением .php."} | верно парсинг: текст (фолбэк) | Остаток имени после префикса, \ → /. |
T09-L4 0.36 c | Пространства имён и автозагрузка | Подключение vendor/autoload.php регистрирует обработчики через spl_autoload_register(). | «да» Пояснение: Файл vendor/autoload.php использует spl_autoload_register() для добавления автозагрузчика Composer.
Raw{"answer": "да", "пояснение": "Файл vendor/autoload.php использует spl_autoload_register() для добавления автозагрузчика Composer."} | верно | Composer ставит автозагрузчик именно на spl_autoload_register. |
T09-L5 0.33 c | Пространства имён и автозагрузка | Магическая константа __NAMESPACE__ содержит имя текущего пространства имён. | «да» Пояснение: Магическая константа __NAMESPACE__ действительно возвращает полное имя текущего пространства имён в виде строки.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Магическая константа __NAMESPACE__ действительно возвращает полное имя текущего пространства имён в виде строки." ⏎ } | верно | В корневом пространстве — пустая строка. |
T09-L6 0.36 c | Пространства имён и автозагрузка | Относительное имя класса (без ведущего \) в new резолвится от глобального корня. | «нет» Пояснение: Относительное имя класса в операторе new резолвится относительно текущего пространства имён, а не от глобального корня.
Raw{"answer": "нет", "пояснение": "Относительное имя класса в операторе new резолвится относительно текущего пространства имён, а не от глобального корня."} | верно | Резолвится относительно текущего namespace (с учётом импортов). |
T09-L7 0.48 c | Пространства имён и автозагрузка | При маппинге PSR-4 «App\ → src/» класс App\Model\User лежит в файле src/Model/User.php. | «да» Пояснение: Согласно стандарту PSR-4, namespace App\Model\User после удаления префикса App\ оставляет Model\User, что соответствует пути src/Model/User.php.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Согласно стандарту PSR-4, namespace App\\Model\\User после удаления префикса App\\ оставляет Model\\User, что соответствует пути src/Model/User.php." ⏎ } | верно | Остаток имени после префикса переносится в путь как есть. |
T09-L8 0.47 c | Пространства имён и автозагрузка | Директиву use можно писать внутри тела функции — импорт будет действовать для этой функции. | «да» Пояснение: В PHP директива use действительно может быть использована внутри тела функции для импорта классов или функций, и этот импорт действует только в пределах этой функции.
Raw{"answer": "да", "пояснение": "В PHP директива use действительно может быть использована внутри тела функции для импорта классов или функций, и этот импорт действует только в пределах этой функции."} | неверно верный: «нет» | use внутри тела функции — parse error; импорты файловые и компиляционные. |
T10-L1 0.44 c | Ссылки и область видимости | Массивы при присваивании копируются, а не передаются по ссылке. | «да» Пояснение: В PHP массивы при присваивании копируются по значению, хотя и используются механизмы копия-on-write для оптимизации.
Raw{"answer": "да", "пояснение": "В PHP массивы при присваивании копируются по значению, хотя и используются механизмы копия-on-write для оптимизации."} | верно | Присваивание массива — копия (в движке — copy-on-write). |
T10-L2 0.4 c | Ссылки и область видимости | Что выведет: $a = [1, 2]; $b = $a; $b[] = 3; echo count($a); | «2» Пояснение: Массивы в PHP по умолчанию копируются при присваивании, поэтому изменение $b не влияет на $a.
Raw{ ⏎ "answer": 2, ⏎ "пояснение": "Массивы в PHP по умолчанию копируются при присваивании, поэтому изменение $b не влияет на $a." ⏎ } | верно | Присваивание — копия: в $a по-прежнему 2 элемента. |
T10-L3 0.54 c | Ссылки и область видимости | Внутри функции пользовательские переменные глобальной области недоступны без global, $GLOBALS или передачи параметром. | «да» Пояснение: В PHP переменные вне функций имеют глобальную область видимости, и для их доступа внутри функций действительно требуется использование оператора global, массива $GLOBALS или передача значения в качестве параметра.
Raw{"answer": "да", "пояснение": "В PHP переменные вне функций имеют глобальную область видимости, и для их доступа внутри функций действительно требуется использование оператора global, массива $GLOBALS или передача значения в качестве параметра."} | верно | Область видимости функций изолирована; исключение — суперглобалы ($_GET и др.). |
T10-L4 0.41 c | Ссылки и область видимости | unset($GLOBALS['x']) внутри функции удаляет глобальную переменную только для этой функции. | «нет» Пояснение: unset() с глобальным массивом $GLOBALS всегда удаляет переменную из глобальной области видимости, независимо от того, где он вызывается.
Raw{"answer": "нет", "пояснение": "unset() с глобальным массивом $GLOBALS всегда удаляет переменную из глобальной области видимости, независимо от того, где он вызывается."} | верно | $GLOBALS — прямое окно в глобальную область: unset удалит её по-настоящему. |
T10-L5 0.32 c | Ссылки и область видимости | Что выведет: function inc(&$x) { $x++; } $n = 5; inc($n); echo $n; | «6» Пояснение: Функция inc() увеличивает значение $n на 1, поэтому $n становится 6.
Raw{"answer": 6, "пояснение": "Функция inc() увеличивает значение $n на 1, поэтому $n становится 6."} | верно | Ссылка меняет оригинал: 6. |
T10-L6 0.61 c | Ссылки и область видимости | Foreach по массиву (по значению) работает с «живым» массивом: изменения массива внутри цикла видны в этом же проходе. | «да» Пояснение: foreach по значению использует внутреннюю указывающую переменную (internal pointer) массива, поэтому изменения массива во время итерации видны в этом же проходе (хотя это и не рекомендуемая практика).
Raw{"answer": "да", "пояснение": "foreach по значению использует внутреннюю указывающую переменную (internal pointer) массива, поэтому изменения массива во время итерации видны в этом же проходе (хотя это и не рекомендуемая практика)."} | неверно верный: «нет» | По значению foreach итерирует копию-снимок. |
T10-L7 0.3 c | Ссылки и область видимости | Статическое свойство класса у каждого экземпляра своё: изменения в одном объекте не видны в других. | «нет» Пояснение: Статические свойства общие для всех экземпляров класса, поэтому изменения в одном объекте видны в других.
Raw{"answer": "нет", "пояснение": "Статические свойства общие для всех экземпляров класса, поэтому изменения в одном объекте видны в других."} | верно | Наоборот: статическое свойство общее для всех экземпляров класса. Проверено php -r. |
T10-L8 0.33 c | Ссылки и область видимости | Массив может иметь булев ключ true, и он сохранится как bool. | «нет» Пояснение: В PHP булевые ключи массивов автоматически преобразуются в целые числа (true -> 1, false -> 0).
Raw{"answer": "нет", "пояснение": "В PHP булевые ключи массивов автоматически преобразуются в целые числа (true -> 1, false -> 0)."} | верно | Булев ключ приводится к int: true → 1, false → 0. |
T11-L1 0.31 c | Генераторы, итераторы, SPL | Внутри генератора можно использовать return со значением, и оно попадёт в $gen->getReturn(). | «да» Пояснение: Метод getReturn() возвращает значение, переданное в оператор return внутри генератора после его завершения.
Raw{"answer": "да", "пояснение": "Метод getReturn() возвращает значение, переданное в оператор return внутри генератора после его завершения."} | верно | return-значение генератора доступно через getReturn() после прохода. |
T11-L2 0.31 c | Генераторы, итераторы, SPL | Полностью пройденный генератор можно «перемотать» через rewind() и пройти снова. | «да» Пояснение: В PHP 8.2 был добавлен метод rewind() для генераторов, позволяющий перезапускать полностью пройденный генератор.
Raw{"answer": "да", "пояснение": "В PHP 8.2 был добавлен метод rewind() для генераторов, позволяющий перезапускать полностью пройденный генератор."} | неверно верный: «нет» | Генератор одноразовый: rewind после начала итерации бросает Exception. |
T11-L3 0.4 c | Генераторы, итераторы, SPL | Конструкция yield from делегирует проход другому генератору или итерируемому объекту. | «да» Пояснение: Конструкция yield from позволяет делегировать генерацию значений от одного генератора к другому или к любому итерируемому объекту.
Raw{"answer": "да", "пояснение": "Конструкция yield from позволяет делегировать генерацию значений от одного генератора к другому или к любому итерируемому объекту."} | верно | yield from проксирует значения, ключи и return-значение внутреннего генератора. |
T11-L4 0.36 c | Генераторы, итераторы, SPL | Что вернёт get_class(g()) для function g() { yield 1; }? | «generator» Пояснение: Функция g() с оператором yield возвращает объект класса Generator, и get_class() возвращает его имя.
Raw{"answer": "Generator", "пояснение": "Функция g() с оператором yield возвращает объект класса Generator, и get_class() возвращает его имя."} | верно | Функция с yield возвращает Generator. |
T11-L5 0.39 c | Генераторы, итераторы, SPL | Сколько элементов вернёт count(iterator_to_array((function () { yield from [1, 2, 3]; })())); | «3» Пояснение: Генератор возвращает три элемента (1, 2, 3), iterator_to_array превращает их в массив из трех элементов.
Raw{"answer": 3, "пояснение": "Генератор возвращает три элемента (1, 2, 3), iterator_to_array превращает их в массив из трех элементов."} | верно | yield from делегирует все 3 элемента. |
T11-L6 0.41 c | Генераторы, итераторы, SPL | Класс SplStack реализует очередь FIFO. | «нет» Пояснение: Класс SplStack реализует структуру данных «стек», которая работает по принципу LIFO (Last-In, First-Out), а не FIFO.
Raw{"answer": "нет", "пояснение": "Класс SplStack реализует структуру данных «стек», которая работает по принципу LIFO (Last-In, First-Out), а не FIFO."} | верно | SplStack — стек LIFO; очередь FIFO — SplQueue. |
T11-L7 0.39 c | Генераторы, итераторы, SPL | ArrayIterator позволяет обернуть массив и обходить его через интерфейс Iterator. | «да» Пояснение: ArrayIterator реализует интерфейсы Iterator, IteratorAggregate и Countable, позволяя обходить массивы как итераторы.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "ArrayIterator реализует интерфейсы Iterator, IteratorAggregate и Countable, позволяя обходить массивы как итераторы." ⏎ } | верно | Объектная обёртка над массивом. |
T11-L8 0.41 c | Генераторы, итераторы, SPL | Объект класса ArrayObject нельзя обойти через foreach. | «да» Пояснение: ArrayObject реализует интерфейс Iterator, поэтому foreach автоматически вызывает методы итератора и безопасно перебирает элементы.
Raw{"answer": "да", "пояснение": "ArrayObject реализует интерфейс Iterator, поэтому foreach автоматически вызывает методы итератора и безопасно перебирает элементы."} | неверно верный: «нет» | ArrayObject реализует IteratorAggregate — foreach по нему работает. |
T12-L1 0.38 c | Конфигурация и безопасность | password_hash() генерирует соль автоматически — передавать её отдельно не нужно. | «да» Пояснение: Функция password_hash() автоматически генерирует и включает соль в итоговую строку хэша, поэтому передавать её вручную не требуется.
Raw{"answer": "да", "пояснение": "Функция password_hash() автоматически генерирует и включает соль в итоговую строку хэша, поэтому передавать её вручную не требуется."} | верно | Соль встраивается в строку результата; параметр salt устарел. |
T12-L2 0.31 c | Конфигурация и безопасность | Алгоритм PASSWORD_DEFAULT в PHP 8 — это md5 с автоматически добавленной солью. | «нет» Пояснение: PASSWORD_DEFAULT в PHP 8 использует алгоритм argon2id (или bcrypt на старых версиях), а не md5.
Raw{"answer": "нет", "пояснение": "PASSWORD_DEFAULT в PHP 8 использует алгоритм argon2id (или bcrypt на старых версиях), а не md5."} | верно | PASSWORD_DEFAULT — bcrypt; md5 для паролей непригоден (перебирается массово). |
T12-L3 0.28 c | Конфигурация и безопасность | Что вернёт password_verify('secret', password_hash('secret', PASSWORD_DEFAULT))? | «да» Пояснение: Функция password_verify сравнивает пароль с хэшем и возвращает true, если они совпадают.
Raw{"answer": "да", "пояснение": "Функция password_verify сравнивает пароль с хэшем и возвращает true, если они совпадают."} | верно | Соль и хеш в одной строке: true (форма ответа: true или да). |
T12-L4 0.33 c | Конфигурация и безопасность | Функция strip_tags() защищает от SQL-инъекций. | «нет» Пояснение: strip_tags() удаляет HTML-теги и защищает от XSS, но не влияет на выполнение SQL-запросов.
Raw{"answer": "нет", "пояснение": "strip_tags() удаляет HTML-теги и защищает от XSS, но не влияет на выполнение SQL-запросов."} | верно | strip_tags режет HTML-теги (помощник против XSS), к параметризации SQL отношения не имеет. |
T12-L5 0.42 c | Конфигурация и безопасность | Функция session_regenerate_id() используется для защиты от фиксации сессии при входе пользователя. | «да» Пояснение: Функция session_regenerate_id() заменяет текущий ID сессии на новый, что является стандартным методом защиты от атак, связанных с фиксацией сессии.
Raw{"answer": "да", "пояснение": "Функция session_regenerate_id() заменяет текущий ID сессии на новый, что является стандартным методом защиты от атак, связанных с фиксацией сессии."} | верно | Новый ID сессии после логина — стандартная защита от session fixation. |
T12-L6 0.35 c | Конфигурация и безопасность | Какая встроенная функция возвращает имя SAPI (например, cli)? | «php_sapi_name» Пояснение: Функция php_sapi_name() возвращает строку с именем текущего интерфейса SAPI (например, 'cli').
Raw{"answer": "php_sapi_name", "пояснение": "Функция php_sapi_name() возвращает строку с именем текущего интерфейса SAPI (например, 'cli')."} | верно | php_sapi_name(). |
T12-L7 0.57 c | Конфигурация и безопасность | session_destroy() удаляет данные сессии на сервере, но не cookie в браузере пользователя. | «да» Пояснение: session_destroy() уничтожает данные сессии на сервере, а cookie с идентификатором сессии остаётся в браузере, если её не удалить вручную через header() и setcookie() со сроком в прошлом.
Raw{"answer": "да", "пояснение": "session_destroy() уничтожает данные сессии на сервере, а cookie с идентификатором сессии остаётся в браузере, если её не удалить вручную через header() и setcookie() со сроком в прошлом."} | верно | Удаление cookie — отдельный шаг через setcookie с истёкшим сроком. |
T12-L8 0.3 c | Конфигурация и безопасность | Без вызова session_start() массив $_SESSION автоматически загружается данными сессии. | «нет» Пояснение: Для загрузки данных сессии в массив $_SESSION необходимо явно вызвать функцию session_start().
Raw{"answer": "нет", "пояснение": "Для загрузки данных сессии в массив $_SESSION необходимо явно вызвать функцию session_start()."} | верно | Без session_start() данные сессии в массив не загружаются ($_SESSION можно заполнить вручную, но привязки к сессии нет). |
VC-L1 0.27 c | PHP 8.4–8.5 | В какой версии PHP появилась функция array_find()? | «php 8.5.0» Пояснение: Функция array_find() была добавлена в PHP 8.5.0.
Raw{"answer": "PHP 8.5.0", "пояснение": "Функция array_find() была добавлена в PHP 8.5.0."} | неверно верный: «8.4» | PHP 8.4 (RFC array_find). |
VC-L2 0.37 c | PHP 8.4–8.5 | Property hooks (get/set прямо в объявлении свойства) вошли в PHP 8.4. | «да» Пояснение: В PHP 8.4 были введены хуки свойств (property hooks), позволяющие использовать ключевые слова get и set непосредственно в объявлении свойств.
Raw{"answer": "да", "пояснение": "В PHP 8.4 были введены хуки свойств (property hooks), позволяющие использовать ключевые слова get и set непосредственно в объявлении свойств."} | верно | Property hooks — PHP 8.4 (ноябрь 2024). |
VC-L3 0.41 c | PHP 8.4–8.5 | Асимметричная видимость (public private(set) string $name) появилась в PHP 8.4. | «да» Пояснение: В PHP 8.4 была добавлена поддержка асимметричной видимости свойств, позволяющая устанавливать модификатор доступа отдельно для чтения и записи.
Raw{"answer": "да", "пояснение": "В PHP 8.4 была добавлена поддержка асимметричной видимости свойств, позволяющая устанавливать модификатор доступа отдельно для чтения и записи."} | верно | Asymmetric visibility v2 — PHP 8.4. |
VC-L4 0.46 c | PHP 8.4–8.5 | В какой версии PHP впервые появился атрибут #[\NoDiscard]? Ответь номером версии. | «нет» Пояснение: Атрибут #[\NoDiscard] в PHP не существует (вероятно, вы имели в виду #[\AllowDynamicProperties] или аналоги из других языков, либо опечатку).
Raw{ ⏎ "answer": "нет", ⏎ "пояснение": "Атрибут #[\\NoDiscard] в PHP не существует (вероятно, вы имели в виду #[\\AllowDynamicProperties] или аналоги из других языков, либо опечатку)." ⏎ } | неверно верный: «8.5» | #[\NoDiscard] — PHP 8.5 (marking return values as important). |
VC-L5 0.35 c | PHP 8.4–8.5 | В какой версии PHP впервые появился оператор конвейера |> (pipe)? Ответь номером версии. | «8.4» Пояснение: Оператор конвейера (pipe operator) был добавлен в PHP 8.4 как новая функциональность.
Raw{"answer": "8.4", "пояснение": "Оператор конвейера (pipe operator) был добавлен в PHP 8.4 как новая функциональность."} | неверно верный: «8.5» | Pipe operator — PHP 8.5 (2025). |
VC-L6 0.4 c | PHP 8.4–8.5 | В какой версии PHP появился clone-with — синтаксис clone($obj, ['x' => 1])? Ответь номером версии. | «нет» Пояснение: В PHP не существует синтаксиса clone с параметром для изменения свойств; операция clone всегда создает поверхностную копию объекта.
Raw{"answer": "нет", "пояснение": "В PHP не существует синтаксиса clone с параметром для изменения свойств; операция clone всегда создает поверхностную копию объекта."} | неверно верный: «8.5» | Clone with v2 — PHP 8.5. |
VC-L7 0.25 c | PHP 8.4–8.5 | В какой версии PHP появились функции array_first() и array_last()? | «8.4» Пояснение: Функции array_first() и array_last() были добавлены в PHP 8.4.
Raw{"answer": "8.4", "пояснение": "Функции array_first() и array_last() были добавлены в PHP 8.4."} | неверно верный: «8.5» | PHP 8.5. |
VC-L8 0.28 c | PHP 8.4–8.5 | Для какой версии PHP был принят RFC Partial Function Application v2 (по состоянию на 07.11.2026)? Ответь номером версии. | «8.4» Пояснение: RFC Partial Function Application v2 был принят для PHP 8.4.
Raw{"answer": "8.4", "пояснение": "RFC Partial Function Application v2 был принят для PHP 8.4."} | неверно верный: «8.6» | PFA v2 принят 05.12.2025 (33-0-0), реализован в PHP 8.6. |
VF-L1 0.26 c | PHP: 8.6+ и будущее | Для какой версии PHP реализован RFC clamp_v2 (функция clamp()) по состоянию на 07.11.2026? Ответь номером версии. | «8.4» Пояснение: Функция clamp() была введена в PHP 8.4.
Raw{"answer": 8.4, "пояснение": "Функция clamp() была введена в PHP 8.4."} | неверно верный: «8.6» | По данным владельца (wiki.php.net/rfc): clamp_v2 — 8.6; clamp() в 8.5.11 отсутствует (косвенное подтверждение). Дата-якорь делает клетку монотонной. |
VF-L2 0.4 c | PHP: 8.6+ и будущее | RFC Context Managers v2 уже принят в PHP (на 07.11.2026). | «нет» Пояснение: На дату 07.11.2026 RFC Context Managers v2 не был принят и включен в стабильную версию PHP.
Raw{"answer": "нет", "пояснение": "На дату 07.11.2026 RFC Context Managers v2 не был принят и включен в стабильную версию PHP."} | верно | На 06.11.2026 — в обсуждении (создан 2026-10-23); не принят. |
VF-L3 0.56 c | PHP: 8.6+ и будущее | RFC Bound-Erased Generic Types (generics) был отклонён в 2026 году. | «да» Пояснение: RFC по дженерикам (Bound-Erased Generic Types) для PHP действительно был отклонён (voted down) в 2024 году, а не принят, поэтому утверждение о его отклонении верно.
Raw{"answer": "да", "пояснение": "RFC по дженерикам (Bound-Erased Generic Types) для PHP действительно был отклонён (voted down) в 2024 году, а не принят, поэтому утверждение о его отклонении верно."} | верно | Голосование завершилось 2026-06-28: отклонён (wiki.php.net/rfc). |
VF-L4 0.58 c | PHP: 8.6+ и будущее | На 07.11.2026 RFC о включении многопоточности (ZTS) по умолчанию уже принят в PHP. | «нет» Пояснение: В настоящее время PHP по умолчанию использует однопоточность (NPT), и RFC по включению многопоточности (ZTS) по умолчанию не принят (на момент моего последнего обновления).
Raw```json ⏎ {"answer": "нет", "пояснение": "В настоящее время PHP по умолчанию использует однопоточность (NPT), и RFC по включению многопоточности (ZTS) по умолчанию не принят (на момент моего последнего обновления)."} ⏎ ``` | верно | Такого принятого RFC нет на дату якоря; якорь делает клетку монотонной — при принятии RFC позже клетка не перевернётся. |
VF-L5 0.61 c | PHP: 8.6+ и будущее | В PHP 8.5 дженериков (параметризованных типов) по-прежнему нет. | «да» Пояснение: На текущий момент (PHP 8.3/8.4) дженериков официально не существует, и в релиз-нотах PHP 8.5 они не запланированы как реализованная функция.
Raw{"answer": "да", "пояснение": "На текущий момент (PHP 8.3/8.4) дженериков официально не существует, и в релиз-нотах PHP 8.5 они не запланированы как реализованная функция."} | верно | Generics в PHP отсутствуют; отрицательный контроль (не путать с C#/Java). |
VF-L6 0.57 c | PHP: 8.6+ и будущее | На 07.11.2026 последняя стабильная версия PHP — 8.5, а PHP 8.6 ещё не выпущена (GA — 19.11.2026). | «да» Пояснение: Согласно официальным планам, PHP 8.5 выходит в ноябре 2025, а PHP 8.6 — в ноябре 2026, поэтому 07.11.2026 актуальна 8.5.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Согласно официальным планам, PHP 8.5 выходит в ноябре 2025, а PHP 8.6 — в ноябре 2026, поэтому 07.11.2026 актуальна 8.5." ⏎ } | верно | 8.5 — релиз осени 2025; 8.6 GA 19.11.2026 (wiki.php.net/todo/php86). Дата снимка — 06.11.2026. |
VF-L7 0.47 c | PHP: 8.6+ и будущее | Ветка PHP 6 так и не вышла: после PHP 5.6 вышел сразу PHP 7.0. | «да» Пояснение: Версия PHP 6 была отменена в 2015 году, чтобы ускорить выход PHP 7.0, которая принесла значительные улучшения производительности.
Raw{"answer": "да", "пояснение": "Версия PHP 6 была отменена в 2015 году, чтобы ускорить выход PHP 7.0, которая принесла значительные улучшения производительности."} | верно | Исторический факт: ветка 6 не была релизнута. |
VF-L8 0.33 c | PHP: 8.6+ и будущее | RFC о добавлении атрибута #[\Deprecated] в ядро был принят. | «да» Пояснение: В PHP 8.4 был добавлен официальный атрибут #[\Deprecated] для декларирования устаревших элементов кода.
Raw{"answer": "да", "пояснение": "В PHP 8.4 был добавлен официальный атрибут #[\\Deprecated] для декларирования устаревших элементов кода."} | верно | #[\Deprecated] — принят, реализован в PHP 8.4. |
T25-L1 0.34 c | Чистая архитектура | Правило зависимостей в чистой и луковичной архитектурах: внутренние слои не знают о внешних — зависимости направлены к центру. | «да» Пояснение: В чистой и луковичной архитектурах все зависимости направлены внутрь, к доменной модели, которая не зависит от внешних компонентов.
Raw{"answer": "да", "пояснение": "В чистой и луковичной архитектурах все зависимости направлены внутрь, к доменной модели, которая не зависит от внешних компонентов."} | верно | Чистая (Robert C. Martin), луковичная (Jeffrey Palermo) и гексагональная (ports & adapters) — варианты одной идеи: зависимости направлены внутрь, к домену. Слоями в проекте следит deptrac. |
T25-L2 0.42 c | Чистая архитектура | Сущности домена не импортируют ни Doctrine, ни Symfony — только язык и, возможно, стандартную библиотеку. | «да» Пояснение: Сущности чистого домена должны зависеть только от PHP и стандартных библиотек, чтобы быть независимыми от фреймворков.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Сущности чистого домена должны зависеть только от PHP и стандартных библиотек, чтобы быть независимыми от фреймворков." ⏎ } | верно | Изоляция домена от инфраструктуры; deptrac в проекте как раз следит за слоями. |
T25-L3 0.42 c | Чистая архитектура | Контроллеры и Twig-шаблоны относятся к слою бизнес-логики, потому что именно они вызывают use cases. | «нет» Пояснение: Контроллеры и шаблоны относятся к прикладному или слою представления (Presentation/Application), а не к бизнес-логике.
Raw{"answer": "нет", "пояснение": "Контроллеры и шаблоны относятся к прикладному или слою представления (Presentation/Application), а не к бизнес-логике."} | верно | Наоборот: это интерфейсные адаптеры (внешний слой); они зависят от use cases, а не наоборот. |
T25-L4 0.37 c | Чистая архитектура | Что находится в самом центре луковичной архитектуры? | «ядро» Пояснение: В центре луковичной архитектуры (например, в операционных системах) находится ядро, обеспечивающее базовую функциональность.
Raw{"answer": "Ядро", "пояснение": "В центре луковичной архитектуры (например, в операционных системах) находится ядро, обеспечивающее базовую функциональность."} | неверно верный: «доменная модель» | Центральное кольцо — Domain Model: сущности и бизнес-правила без зависимостей; далее Domain Services → Application Services → Infrastructure/UI/Tests (Palermo). |
T25-L5 0.36 c | Чистая архитектура | Нарушение границ слоёв можно поймать автоматикой: анализатор зависимостей между слоями (например, deptrac) падает на запрещённом вызове. | «да» Пояснение: Инструменты типа deptrac автоматически анализируют зависимости и блокируют сборку при нарушении правил между слоями.
Raw{"answer": "да", "пояснение": "Инструменты типа deptrac автоматически анализируют зависимости и блокируют сборку при нарушении правил между слоями."} | верно | depfile.yaml в проекте TasK: CI проверяет правила слоёв на каждом пайплайне. |
T25-L6 0.61 c | Чистая архитектура | Use case (interactor) может принимать HTTP-запрос или EntityManager как аргументы — так проще. | «нет» Пояснение: Исполнитель (Use Case/Interactor) должен быть независимым от HTTP и реализации ORM (EntityManager), принимая абстракции (интерфейсы) или чистые данные.
Raw{"answer": "нет", "пояснение": "Исполнитель (Use Case/Interactor) должен быть независимым от HTTP и реализации ORM (EntityManager), принимая абстракции (интерфейсы) или чистые данные."} | верно | Use case принимает DTO и порты; привязка к HTTP/ORM протекает инфраструктуру во внутренние слои. |
T25-L7 0.38 c | Чистая архитектура | Как называется компонент, предоставляющий коллекцию агрегатов/сущностей, скрывая механизм хранения за интерфейсом? | «repository» Пояснение: Repository — это паттерн, который предоставляет интерфейс для доступа к коллекции доменных объектов, абстрагируя механизм их хранения.
Raw{"answer": "Repository", "пояснение": "Repository — это паттерн, который предоставляет интерфейс для доступа к коллекции доменных объектов, абстрагируя механизм их хранения."} | верно | Repository pattern (DDD/Evans); в проекте — Doctrine-репозитории за портами. |
T25-L8 0.48 c | Чистая архитектура | Замена PostgreSQL на другую БД в чистой архитектуре затрагивает только внешний слой — домен и use cases не меняются. | «да» Пояснение: В чистой архитектуре домен и use cases зависят от интерфейсов (порт), а конкретная реализация БД является деталью внешнего слоя, что позволяет менять СУБД без изменения внутренней логики.
Raw{"answer": "да", "пояснение": "В чистой архитектуре домен и use cases зависят от интерфейсов (порт), а конкретная реализация БД является деталью внешнего слоя, что позволяет менять СУБД без изменения внутренней логики."} | верно | Следствие правила зависимостей: инфраструктура взаимозаменяема. |
T26-L1 0.48 c | DDD | Агрегат в DDD — это просто другое название таблицы базы данных. | «нет» Пояснение: Агрегат в DDD — это кластер сущностей и значений, представляющий собой единую единицу целостности доменной модели, а не просто таблица БД.
Raw{"answer": "нет", "пояснение": "Агрегат в DDD — это кластер сущностей и значений, представляющий собой единую единицу целостности доменной модели, а не просто таблица БД."} | верно | Агрегат — кластер объектов с границей согласованности (транзакционной вокруг корня); таблица — деталь хранения. |
T26-L2 0.38 c | DDD | Value Object неизменяем и сравнивается по значениям полей, а не по идентификатору. | «да» Пояснение: Value Object определяются своими полями, являются неизменяемыми (immutable) и сравниваются по содержимому, а не по ссылке или ID.
Raw{"answer": "да", "пояснение": "Value Object определяются своими полями, являются неизменяемыми (immutable) и сравниваются по содержимому, а не по ссылке или ID."} | верно | Классика Evans: Money, Email; равенство структурное. |
T26-L3 0.36 c | DDD | Как называется единственная точка внешнего входа в агрегат, через которую проходят все изменения? | «агрегатный корень» Пояснение: В DDD агрегатный корень является единственной точкой внешнего входа для операций с агрегатом.
Raw{"answer": "Агрегатный корень", "пояснение": "В DDD агрегатный корень является единственной точкой внешнего входа для операций с агрегатом."} | верно | Aggregate Root: внешние объекты ссылаются только на корень; он защищает инварианты агрегата. |
T26-L4 0.43 c | DDD | В DDD репозиторий объявляется на агрегат (его корень), а не на каждую сущность. | «да» Пояснение: В DDD репозиторий инкапсулирует доступ к агрегату как к единому целому, обеспечивая целостность состояния через его корневую сущность.
Raw{"answer": "да", "пояснение": "В DDD репозиторий инкапсулирует доступ к агрегату как к единому целому, обеспечивая целостность состояния через его корневую сущность."} | верно | Репозиторий корня хранит границу согласованности агрегата; вложенные сущности доступны только через корень. |
T26-L5 0.51 c | DDD | Ubiquitous language — единый язык модели, общий для разработчиков и предметных экспертов. | «да» Пояснение: Ubiquitous language (Универсальный язык) действительно является общим языком модели, используемым всеми участниками проекта для точного и однозначного обсуждения предметной области.
Raw{"answer": "да", "пояснение": "Ubiquitous language (Универсальный язык) действительно является общим языком модели, используемым всеми участниками проекта для точного и однозначного обсуждения предметной области."} | верно | Evans: язык из требований переходит в имена классов и методов. |
T26-L6 0.54 c | DDD | Как называется граница, внутри которой модель и её язык едины, а снаружи те же понятия — другие модели? | «парадигма» Пояснение: Парадигма определяет стиль и правила программирования, формируя единое представление о моделях данных и их использовании в пределах конкретного языка или подхода.
Raw{"answer": "парадигма", "пояснение": "Парадигма определяет стиль и правила программирования, формируя единое представление о моделях данных и их использовании в пределах конкретного языка или подхода."} | неверно верный: «bounded context» | Bounded Context; «Заказ» в биллинге и в доставке — разные модели. |
T26-L7 0.52 c | DDD | Анемичная модель (объекты только с геттерами/сеттерами, логика в сервисах) — рекомендуемый стиль DDD. | «нет» Пояснение: В DDD рекомендуется использовать богатые доменные модели, где бизнес-логика инкапсулирована внутри сущностей, а анемичные модели противоречат принципам DDD.
Raw{"answer": "нет", "пояснение": "В DDD рекомендуется использовать богатые доменные модели, где бизнес-логика инкапсулирована внутри сущностей, а анемичные модели противоречат принципам DDD."} | верно | Наоборот: Evans называет анемичность антипаттерном — поведение должно жить в доменных объектах. |
T26-L8 0.45 c | DDD | Bounded context означает, что у каждого контекста своя модель: одно и то же понятие в разных контекстах — разные классы. | «да» Пояснение: Бounded context ограничивает область применимости одной бизнес-модели, позволяя одному и тому же термину иметь разные определения и реализации в разных контекстах.
Raw{"answer": "да", "пояснение": "Бounded context ограничивает область применимости одной бизнес-модели, позволяя одному и тому же термину иметь разные определения и реализации в разных контекстах."} | верно | Модели контекстов независимы; между ними — явная интеграция (ACL, published language). |
T13-L1 0.72 c | Symfony | Сервисы в DI-контейнере Symfony по умолчанию создаются лениво — при первом обращении к ним. | «да» Пояснение: По умолчанию сервисы в Symfony создаются лениво, если они публичные и не помечены как singleton, но если это private-сервисы, то они могут быть созданы сразу при компиляции контейнера. Однако в общем случае, особенно для публичных сервисов, они создаются лениво при первом обращении.
Raw{"answer": "да", "пояснение": "По умолчанию сервисы в Symfony создаются лениво, если они публичные и не помечены как singleton, но если это private-сервисы, то они могут быть созданы сразу при компиляции контейнера. Однако в общем случае, особенно для публичных сервисов, они создаются лениво при первом обращении."} | верно | Контейнер инстанцирует сервис при первом извлечении; eager-создания по умолчанию нет. |
T13-L2 0.34 c | Symfony | Какая консольная команда Symfony выводит список всех зарегистрированных маршрутов? | «bin/console debug:router» Пояснение: Команда debug:router выводит список всех зарегистрированных маршрутов в Symfony.
Raw{"answer": "bin/console debug:router", "пояснение": "Команда debug:router выводит список всех зарегистрированных маршрутов в Symfony."} | верно | bin/console debug:router (FrameworkBundle); в Symfony 3 команда называлась router:debug. |
T13-L3 0.33 c | Symfony | Autowiring в Symfony требует вручную перечислять каждый сервис в конфигурации services.yaml. | «нет» Пояснение: Autowiring позволяет автоматически подставлять зависимости по типу без ручного перечисления каждого сервиса в конфигурации.
Raw{"answer": "нет", "пояснение": "Autowiring позволяет автоматически подставлять зависимости по типу без ручного перечисления каждого сервиса в конфигурации."} | верно | Autowire+autoconfigure регистрируют и связывают сервисы автоматически; ручное перечисление — исключение. |
T13-L4 0.33 c | Symfony | Twig-шаблоны компилируются в PHP-классы и кэшируются между запросами. | «да» Пояснение: Twig компилирует шаблоны в PHP-код и сохраняет его в кэш для повторного использования при последующих запросах.
Raw{"answer": "да", "пояснение": "Twig компилирует шаблоны в PHP-код и сохраняет его в кэш для повторного использования при последующих запросах."} | верно | Twig компилирует шаблон один раз; кэш в var/cache/twig, в prod не пересобирается. |
T13-L5 0.48 c | Symfony | Контейнер DI в dev-окружении Symfony пересобирается только после изменения отслеживаемых файлов, а не при каждом запросе. | «да» Пояснение: В dev-окружении Symfony контейнер кэшируется и пересобирается только при изменении отслеживаемых файлов (через hash в cache), а не при каждом запросе.
Raw{"answer": "да", "пояснение": "В dev-окружении Symfony контейнер кэшируется и пересобирается только при изменении отслеживаемых файлов (через hash в cache), а не при каждом запросе."} | верно | Kernel проверяет freshness ресурсов (конфиги, классы); иначе переиспользуется кэш контейнера. |
T13-L6 0.39 c | Symfony | Какая переменная окружения выбирает активное окружение Symfony (dev/prod)? | «app_env» Пояснение: Переменная окружения APP_ENV в Symfony определяет текущий режим приложения (например, dev или prod).
Raw{"answer": "APP_ENV", "пояснение": "Переменная окружения APP_ENV в Symfony определяет текущий режим приложения (например, dev или prod)."} | верно | APP_ENV в .env; APP_DEBUG — отдельный флаг отладки. |
T13-L7 0.34 c | Symfony | Метод контроллера может быть private — маршрутизация Symfony работает с любыми методами класса. | «нет» Пояснение: Маршрутизация Symfony требует, чтобы методы контроллера были публичными (public), так как фреймворк вызывает их извне.
Raw{"answer": "нет", "пояснение": "Маршрутизация Symfony требует, чтобы методы контроллера были публичными (public), так как фреймворк вызывает их извне."} | верно | Действие контроллера должно быть public; приватный метод по маршруту не вызывается. |
T13-L8 0.38 c | Symfony | Подписчики событий (EventSubscriber) всегда получают события раньше слушателей (listeners), потому что интерфейс даёт им приоритет. | «нет» Пояснение: Приоритет события определяется параметром $priority в методе getSubscribedEvents, а не типом класса (Listener или Subscriber).
Raw{"answer": "нет", "пояснение": "Приоритет события определяется параметром $priority в методе getSubscribedEvents, а не типом класса (Listener или Subscriber)."} | верно | Порядок определяет priority, а не тип подписки; приоритеты задаются в getSubscribedEvents() так же, как у слушателей. |
T22-L1 0.44 c | Symfony: Security и формы | В современном Symfony (6.0+) аутентификация строится на классах-authenticator (AuthenticatorInterface); прежняя система guard удалена. | «да» Пояснение: Система guard была удалена в Symfony 5.3, а в Symfony 6+ аутентификация строится исключительно на AuthenticatorInterface.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Система guard была удалена в Symfony 5.3, а в Symfony 6+ аутентификация строится исключительно на AuthenticatorInterface." ⏎ } | верно | Guard объявлен устаревшим в 5.3 и удалён в 6.0; в проекте symfony/security-bundle 8.1. |
T22-L2 0.34 c | Symfony: Security и формы | Какой атрибут Symfony проверяет роль/право прямо на методе контроллера (без него — 403)? | «isgranted» Пояснение: Атрибут #[IsGranted] проверяет права доступа прямо на методе контроллера.
Raw{"answer": "IsGranted", "пояснение": "Атрибут #[IsGranted] проверяет права доступа прямо на методе контроллера."} | верно | #[IsGranted('ROLE_ADMIN')]; атрибут из symfony/security-http. |
T22-L3 0.33 c | Symfony: Security и формы | Voters (голосующие) — механизм Symfony для проверки доступа к конкретному объекту: isGranted('EDIT', $post). | «да» Пояснение: Voters в Symfony действительно используются для проверки доступа к конкретным объектам через метод isGranted() с указанием действия и объекта.
Raw{"answer": "да", "пояснение": "Voters в Symfony действительно используются для проверки доступа к конкретным объектам через метод isGranted() с указанием действия и объекта."} | верно | VoterInterface->vote(); docs Symfony — Voters. |
T22-L4 0.52 c | Symfony: Security и формы | Ограничения валидации в современных Symfony (7+) объявляются PHP-атрибутами (#[Assert\NotBlank]); аннотации-докблоки больше не поддерживаются. | «да» Пояснение: Начиная с Symfony 6, док-блок аннотации (Annotations) официально удалены, и для ограничений валидации используются исключительно PHP-атрибуты (Attributes).
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Начиная с Symfony 6, док-блок аннотации (Annotations) официально удалены, и для ограничений валидации используются исключительно PHP-атрибуты (Attributes)." ⏎ } | верно | Докблок-аннотации удалены в Symfony 7.0; стандарт — атрибуты. В проекте symfony/validator 8.1. |
T22-L5 0.41 c | Symfony: Security и формы | CSRF-защита форм в Symfony включена по умолчанию: форма проверяет токен при отправке. | «да» Пояснение: Symfony автоматически генерирует и проверяет CSRF-токены для форм, если компонент Forms установлен.
Raw{"answer": "да", "пояснение": "Symfony автоматически генерирует и проверяет CSRF-токены для форм, если компонент Forms установлен."} | верно | FormType добавляет скрытое поле _token и проверяет его при валидации; отключение — осознанное исключение (csrf: false). |
T22-L6 0.3 c | Symfony: Security и формы | Валидация формы в Symfony выполняется на сервере, даже если клиентская (HTML5) проверка прошла. | «да» Пояснение: Symfony выполняет серверную валидацию всегда, независимо от результатов клиентской HTML5 проверки.
Raw{"answer": "да", "пояснение": "Symfony выполняет серверную валидацию всегда, независимо от результатов клиентской HTML5 проверки."} | верно | Клиентская валидация — только удобство; серверная обязательна и идёт по метаданным объекта формы. |
T22-L7 0.32 c | Symfony: Security и формы | Какая команда Symfony maker генерирует класс формы (FormType)? | «make:form» Пояснение: Команда bin/console make:form создает класс формы в Symfony Maker Bundle.
Raw{"answer": "make:form", "пояснение": "Команда bin/console make:form создает класс формы в Symfony Maker Bundle."} | верно | bin/console make:form (symfony/maker-bundle — в проекте). |
T22-L8 0.59 c | Symfony: Security и формы | Symfony хранит пароль пользователя в сессии в открытом виде (plaintext). | «нет» Пояснение: Symfony не хранит пароли в сессии; после аутентификации сессия содержит токен, ID пользователя или другие метаданные, а пароль остается в хешированном виде в базе данных.
Raw{"answer": "нет", "пояснение": "Symfony не хранит пароли в сессии; после аутентификации сессия содержит токен, ID пользователя или другие метаданные, а пароль остается в хешированном виде в базе данных."} | верно | В сессии живёт объект пользователя в токене; хеш затирается eraseCredentials(), plaintext там никогда не лежит. |
T23-L1 0.38 c | Symfony: конфигурация и сервисы | Конфигурация бандлов Symfony лежит в config/packages — по одному файлу на бандл или тему. | «да» Пояснение: Конфигурация Symfony действительно хранится в config/packages, где каждый файл соответствует одному бандлу или конкретной теме.
Raw```json ⏎ {"answer": "да", "пояснение": "Конфигурация Symfony действительно хранится в config/packages, где каждый файл соответствует одному бандлу или конкретной теме."} ⏎ ``` | верно | Стандартная структура (config/packages/*.yaml); перегрузка — config/packages/<env>. |
T23-L2 0.49 c | Symfony: конфигурация и сервисы | Файл .env с dev-дефолтами коммитится в репозиторий, а настоящие секреты живут в некоммитимом .env.local. | «да» Пояснение: Это стандартная практика: .env содержит безопасные значения по умолчанию для разработки и коммитится, а .env.local хранит чувствительные секреты и исключается из контроля версий.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Это стандартная практика: .env содержит безопасные значения по умолчанию для разработки и коммитится, а .env.local хранит чувствительные секреты и исключается из контроля версий." ⏎ } | верно | symfony/dotenv: .env — общий безопасный набор значений; локальные секреты — .env.local (gitignored) или secrets-хранилище. |
T23-L3 0.37 c | Symfony: конфигурация и сервисы | Какая команда Symfony выводит зарегистрированные сервисы контейнера и их алиасы? | «bin/console debug:container» Пояснение: Команда debug:container в Symfony выводит список зарегистрированных сервисов и их алиасов.
Raw{"answer": "bin/console debug:container", "пояснение": "Команда debug:container в Symfony выводит список зарегистрированных сервисов и их алиасов."} | верно | bin/console debug:container; параметры контейнера — debug:parameter. |
T23-L4 0.33 c | Symfony: конфигурация и сервисы | Контейнер Symfony позволяет менять параметры в рантайме: $container->setParameter() работает из контроллера. | «нет» Пояснение: Метод setParameter() доступен только при компиляции контейнера и вызывает исключение в рантайме.
Raw{"answer": "нет", "пояснение": "Метод setParameter() доступен только при компиляции контейнера и вызывает исключение в рантайме."} | верно | Контейнер компилируется и замораживается; runtime-значения — только через переменные окружения. |
T23-L5 0.36 c | Symfony: конфигурация и сервисы | По умолчанию сервисы в Symfony публичны (public: true) — их достают из контейнера напрямую. | «нет» Пояснение: По умолчанию сервисы в Symfony приватные (private: true), и их нельзя извлекать напрямую из контейнера.
Raw{"answer": "нет", "пояснение": "По умолчанию сервисы в Symfony приватные (private: true), и их нельзя извлекать напрямую из контейнера."} | верно | С Symfony 4.0 сервисы по умолчанию private: инжектятся через autowiring; $container->get() — только для публичных. |
T23-L6 0.38 c | Symfony: конфигурация и сервисы | Без конфигурационного файла в config/packages бандл не заработает — настройки обязательны для каждого бандла. | «нет» Пояснение: Бандлы работают с настройками по умолчанию, если их конфигурация не требуется для базовой функциональности.
Raw{"answer": "нет", "пояснение": "Бандлы работают с настройками по умолчанию, если их конфигурация не требуется для базовой функциональности."} | верно | У бандлов есть встроенные умолчания (Extension); конфиг нужен только для отклонений от них. |
T23-L7 0.34 c | Symfony: конфигурация и сервисы | Значения переменных окружения подставляются в services.yaml синтаксисом %env(VAR)%. | «да» Пояснение: В Symfony значения переменных окружения действительно подставляются через синтаксис %env(NAME)%.
Raw{"answer": "да", "пояснение": "В Symfony значения переменных окружения действительно подставляются через синтаксис %env(NAME)%."} | верно | %env(...)% резолвится в рантайме env-процессорами; docs — Env Var Processors. |
T23-L8 0.27 c | Symfony: конфигурация и сервисы | Какая переменная окружения Symfony включает режим отладки (влияет на профайлер и отладку Twig)? | «app_debug» Пояснение: Переменная окружения APP_DEBUG управляет включением режима отладки в Symfony.
Raw{"answer": "APP_DEBUG", "пояснение": "Переменная окружения APP_DEBUG управляет включением режима отладки в Symfony."} | верно | APP_DEBUG=1 (в .env dev-окружения); окружение выбирает APP_ENV — см. T13-L6. |
T16-L1 0.35 c | Symfony: Messenger | Одно сообщение в Symfony Messenger может обрабатывать только один обработчик (handler). | «нет» Пояснение: В Symfony Messenger одно сообщение может обрабатываться несколькими обработчиками (handlers), которые выполняются последовательно.
Raw{"answer": "нет", "пояснение": "В Symfony Messenger одно сообщение может обрабатываться несколькими обработчиками (handlers), которые выполняются последовательно."} | верно | Messenger вызывает все хендлеры, подписанные на класс сообщения (docs — Multiple Handlers). |
T16-L2 0.38 c | Symfony: Messenger | Транспорт sync в Messenger ставит сообщение в очередь и обрабатывает его воркером, как и async. | «нет» Пояснение: Транспорт sync обрабатывает сообщение синхронно в текущем процессе немедленно, не ставя его в очередь и не требуя воркера.
Raw{"answer": "нет", "пояснение": "Транспорт sync обрабатывает сообщение синхронно в текущем процессе немедленно, не ставя его в очередь и не требуя воркера."} | верно | Наоборот: sync обрабатывает немедленно в том же процессе, что и отправка; очередь — это async-транспорт. |
T16-L3 0.37 c | Symfony: Messenger | Какой консольной командой запускается воркер, обрабатывающий сообщения из очередей Messenger? | «console messenger:consume» Пояснение: Для запуска воркера, обрабатывающего сообщения из очередей Symfony Messenger, используется команда 'console messenger:consume'.
Raw{"answer": "console messenger:consume", "пояснение": "Для запуска воркера, обрабатывающего сообщения из очередей Symfony Messenger, используется команда 'console messenger:consume'."} | верно | bin/console messenger:consume async; воркеры под supervisord/systemd в проде. |
T16-L4 0.37 c | Symfony: Messenger | Повторы неудачных сообщений (retry_strategy) настраиваются на уровне транспорта Messenger. | «да» Пояснение: В Symfony Messenger политика повторов (retry_strategy) настраивается в конфигурации транспортного механизма (transport) через параметр retry_strategy.
Raw{"answer": "да", "пояснение": "В Symfony Messenger политика повторов (retry_strategy) настраивается в конфигурации транспортного механизма (transport) через параметр retry_strategy."} | верно | retry_strategy на транспорте: max_retries, delay, multiplier; docs — Failed Messages & Retries. |
T16-L5 0.3 c | Symfony: Messenger | По умолчанию Messenger сериализует сообщения в JSON. | «да» Пояснение: По умолчанию в Symfony Messenger используется сериализация в JSON (JsonSerializer).
Raw{"answer": "да", "пояснение": "По умолчанию в Symfony Messenger используется сериализация в JSON (JsonSerializer)."} | неверно верный: «нет» | Дефолтный сериализатор — PhpSerializer (serialize()); JSON-сериализатор включается отдельно. |
T16-L6 0.37 c | Symfony: Messenger | Symfony Scheduler по расписанию порождает сообщения и отправляет их через Messenger. | «да» Пояснение: Symfony Scheduler (ранее Scheduler bundle) позволяет выполнять задачи по расписанию, которые могут диспетчеризировать сообщения через Symfony Messenger.
Raw{"answer": "да", "пояснение": "Symfony Scheduler (ранее Scheduler bundle) позволяет выполнять задачи по расписанию, которые могут диспетчеризировать сообщения через Symfony Messenger."} | верно | Schedule → RecurringMessage → шина Messenger; docs — Scheduler. |
T16-L7 0.31 c | Symfony: Messenger | Какой встроенный транспорт Messenger хранит сообщения в таблицах БД через Doctrine? | «doctrine» Пояснение: Транспорт `doctrine` в Symfony Messenger использует Doctrine ORM для хранения сообщений в таблицах базы данных.
Raw{"answer": "doctrine", "пояснение": "Транспорт `doctrine` в Symfony Messenger использует Doctrine ORM для хранения сообщений в таблицах базы данных."} | верно | Транспорт doctrine (symfony/doctrine-messenger); таблица messenger_messages. В проекте стоит amqp-messenger + doctrine-messenger. |
T16-L8 0.47 c | Symfony: Messenger | Пайплайн Messenger можно расширять собственными middleware, встраивая их до или после встроенных. | «да» Пояснение: В Laravel Messenger можно добавлять собственные middleware в pipeline, указывая их до или после встроенных (например, ThrottlesRateLimit, DispatchesJobs).
Raw{"answer": "да", "пояснение": "В Laravel Messenger можно добавлять собственные middleware в pipeline, указывая их до или после встроенных (например, ThrottlesRateLimit, DispatchesJobs)."} | верно | messenger.bus.*.middleware в yaml; docs — Middleware. |
T28-L1 4.52 c | Symfony: версии | Мажорные релизы Symfony выходят раз в два года, минорные — каждые шесть месяцев (в мае и ноябре). | «нет» Пояснение: Минорные версии Symfony выходят каждые полгода, но их даты привязаны к версиям PHP и обычно выпадают на май и ноябрь, однако утверждение о строгом цикле "каждые шесть месяцев" без учета переходных периодов и поддержки LTS может быть неточным в контексте жизненного цикла конкретных мажорных версий, но главное — мажорные релизы (новые мажорные версии, как 7.0, 8.0) выходят примерно раз в 2 года, что верно, но формулировка вопроса часто ловит на том, что минорные патчи выходят чаще, а "минорные релизы" в значении новых функциональных обновлений действительно каждые полгода. Однако, строго говоря, мажорные релизы (новые мажорные номера) выходят раз в 2 года, а минорные (новые минорные номера) — каждые полгода. Утверждение верно в общих чертах для стабильных релизов. Но есть нюанс: после выхода мажорной версии, минорные релизы этой ветки выходят каждые 6 месяцев. Вопрос сформулирован как факт о регулярности. Обычно это считается верным утверждением в документации Symfony. Однако, давайте перепроверим: Symfony 7.0 вышел в мае 2023, Symfony 7.1 в ноябре 2023. Symfony 6.4 (LTS) получил поддержку до 2027. Новые мажорные (8.0) ожидаются в 2025. Цикл мажорных версий (новые мажорные номера) действительно ~2 года. Минорные (новые минорные номера в рамках текущей мажорной) — каждые 6 месяцев. Утверждение верно. Но почему тогда ответ "нет"? Возможно, подвох в том, что мажорные релизы (как 5.0, 6.0, 7.0) вышли в мае 2021, мае 2023. Это 2 года. Минорные: 7.0 (май 23), 7.1 (ноя 23), 7.2 (май 24), 7.3 (ноя 24). Это каждые 6 месяцев. Так что утверждение Верно. Почему я выбрал "нет"? Возможно, я ошибся. Давайте посмотрим на типичные вопросы. Часто говорят, что мажорные версии выходят раз в 2 года, а минорные — каждые 6 месяцев. Это стандартный цикл Symfony. Значит, ответ должен быть "да". Я пересматриваю свой выбор. Да, это верное утверждение.
Raw{"answer": "нет", "пояснение": "Минорные версии Symfony выходят каждые полгода, но их даты привязаны к версиям PHP и обычно выпадают на май и ноябрь, однако утверждение о строгом цикле \"каждые шесть месяцев\" без учета переходных периодов и поддержки LTS может быть неточным в контексте жизненного цикла конкретных мажорных версий, но главное — мажорные релизы (новые мажорные версии, как 7.0, 8.0) выходят примерно раз в 2 года, что верно, но формулировка вопроса часто ловит на том, что минорные патчи выходят чаще, а \"минорные релизы\" в значении новых функциональных обновлений действительно каждые полгода. Однако, строго говоря, мажорные релизы (новые мажорные номера) выходят раз в 2 года, а минорные (новые минорные номера) — каждые полгода. Утверждение верно в общих чертах для стабильных релизов. Но есть нюанс: после выхода мажорной версии, минорные релизы этой ветки выходят каждые 6 месяцев. Вопрос сформулирован как факт о регулярности. Обычно это считается верным утверждением в документации Symfony. Однако, давайте перепроверим: Symfony 7.0 вышел в мае 2023, Symfony 7.1 в ноябре 2023. Symfony 6.4 (LTS) получил поддержку до 2027. Новые мажорные (8.0) ожидаются в 2025. Цикл мажорных версий (новые мажорные номера) действительно ~2 года. Минорные (новые минорные номера в рамках текущей мажорной) — каждые 6 месяцев. Утверждение верно. Но почему тогда ответ \"нет\"? Возможно, подвох в том, что мажорные релизы (как 5.0, 6.0, 7.0) вышли в мае 2021, мае 2023. Это 2 года. Минорные: 7.0 (май 23), 7.1 (ноя 23), 7.2 (май 24), 7.3 (ноя 24). Это каждые 6 месяцев. Так что утверждение Верно. Почему я выбрал \"нет\"? Возможно, я ошибся. Давайте посмотрим на типичные вопросы. Часто говорят, что мажорные версии выходят раз в 2 года, а минорные — каждые 6 месяцев. Это стандартный цикл Symfony. Значит, ответ должен быть \"да\". Я пересматриваю свой выбор. Да, это верное утверждение."} | неверно верный: «да» | Стандартный релизный цикл: 8.0 — ноябрь 2025, 8.1 — май 2026, 8.2 — ноябрь 2026. |
T28-L2 0.33 c | Symfony: версии | Какой минимальной версии PHP требует Symfony 8? | «8.4» Пояснение: Symfony 8 требует минимально PHP 8.4.
Raw{"answer": "8.4", "пояснение": "Symfony 8 требует минимально PHP 8.4."} | верно | Symfony 8.0 поднял требование до PHP >= 8.4.1 (в vendor проекта: "php": ">=8.4.1"). |
T28-L3 0.43 c | Symfony: версии | Symfony 7.0 сохранила поддержку аннотаций в докблоках (валидация, маршруты). | «нет» Пояснение: В Symfony 7.0 поддержка аннотаций (докблоков) для маршрутов и валидации была полностью удалена в пользу PHP-атрибутов.
Raw{"answer": "нет", "пояснение": "В Symfony 7.0 поддержка аннотаций (докблоков) для маршрутов и валидации была полностью удалена в пользу PHP-атрибутов."} | верно | Наоборот: в 7.0 аннотации удалены — только PHP-атрибуты (#[Route], #[Assert\NotBlank]). |
T28-L4 0.48 c | Symfony: версии | AssetMapper позволяет управлять CSS/JS без node и webpack — через importmap.php. | «да» Пояснение: AssetMapper в Symfony (через package:stimulus/asset-mapper) действительно управляет CSS/JS без node/webpack, используя importmap.php.
Raw{"answer": "да", "пояснение": "AssetMapper в Symfony (через package:stimulus/asset-mapper) действительно управляет CSS/JS без node/webpack, используя importmap.php."} | верно | symfony/asset-mapper (с 6.3, стандарт с 7.x); в проекте — importmap.php в корне и asset-mapper 8.1. |
T28-L5 0.32 c | Symfony: версии | Symfony 6.4 — обычный релиз без длительной поддержки. | «нет» Пояснение: Symfony 6.4 является LTS (Long-Term Support) релизом, обеспечивающим расширенную поддержку.
Raw{"answer": "нет", "пояснение": "Symfony 6.4 является LTS (Long-Term Support) релизом, обеспечивающим расширенную поддержку."} | верно | Наоборот: 6.4 — LTS (расширенная поддержка); LTS выходит вместе с очередным мажором (6.4 — вместе с 7.0). |
T28-L6 0.43 c | Symfony: версии | При переходе на новую мажорную версию Symfony деприкейшены прошлой ветки продолжают работать — мажорные релизы их не удаляют. | «нет» Пояснение: Мажорные релизы Symfony удаляют функциональность, помеченную как deprecated в предыдущей мажорной версии, согласно политике версиирования (SemVer).
Raw{"answer": "нет", "пояснение": "Мажорные релизы Symfony удаляют функциональность, помеченную как deprecated в предыдущей мажорной версии, согласно политике версиирования (SemVer)."} | верно | Наоборот: мажорный релиз удаляет всё устаревшее (7.0 убрал деприкейшены 6.x, 8.0 — 7.x). |
T28-L7 0.64 c | Symfony: версии | Каждый мажорный релиз Symfony сопровождается UPGRADE-гайдом со списком изменений. | «нет» Пояснение: Symfony предоставляет документацию об изменениях (Changelog/Upgrade Guide), но не обязательный единый UPGRADE-гайд со списком всех изменений для каждого мажорного релиза, так как пакетная система позволяет обновлять компоненты независимо.
Raw{"answer": "нет", "пояснение": "Symfony предоставляет документацию об изменениях (Changelog/Upgrade Guide), но не обязательный единый UPGRADE-гайд со списком всех изменений для каждого мажорного релиза, так как пакетная система позволяет обновлять компоненты независимо."} | неверно верный: «да» | UPGRADE-7.0.md, UPGRADE-8.0.md в репозитории symfony/symfony. |
T28-L8 0.95 c | Symfony: версии | Какой компонент Symfony управляет ассетами и importmap без node/webpack? | «webpackencorebundle» Пояснение: WebpackEncoreBundle интегрирует Webpack (часто с Encore.js) в Symfony для управления ассетами, хотя сам по себе это не замена node/webpack, а мост к ним; если же речь идет об importmap без node, то это AssetMapper (симфонийный компонент, входящий в AssetMapperBundle).
Raw{"answer": "WebpackEncoreBundle", "пояснение": "WebpackEncoreBundle интегрирует Webpack (часто с Encore.js) в Symfony для управления ассетами, хотя сам по себе это не замена node/webpack, а мост к ним; если же речь идет об importmap без node, то это AssetMapper (симфонийный компонент, входящий в AssetMapperBundle)."} | неверно верный: «asset-mapper» | symfony/asset-mapper 8.1 — в проекте. |
T29-L1 0.47 c | Symfony: 8.2 и будущее | На 07.11.2026 Symfony 8.2 уже выпущена. | «нет» Пояснение: На 07.11.2026 Symfony 8.2 еще не выпущена, так как Symfony 8.0 планируется к выпуску только в ноябре 2027 года.
Raw{"answer": "нет", "пояснение": "На 07.11.2026 Symfony 8.2 еще не выпущена, так как Symfony 8.0 планируется к выпуску только в ноябре 2027 года."} | верно | Наоборот: 8.2 ещё не выпущена — релиз в конце ноября 2026; последняя стабильная — 8.1. |
T29-L2 0.58 c | Symfony: 8.2 и будущее | По состоянию на 07.11.2026 Symfony 8.2 запланирована на ноябрь 2026 — в обычном шестимесячном цикле. | «да» Пояснение: Symfony следует шестимесячному циклу релизов (май и ноябрь), поэтому версия 8.2, выходящая после 8.1 (май 2026), запланирована на ноябрь 2026.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Symfony следует шестимесячному циклу релизов (май и ноябрь), поэтому версия 8.2, выходящая после 8.1 (май 2026), запланирована на ноябрь 2026." ⏎ } | верно | Политика релизов: 8.1 — май 2026, 8.2 — ноябрь 2026; якорь даты фиксирует срез — модель с поздним cutoff отвечает «на дату». |
T29-L3 0.49 c | Symfony: 8.2 и будущее | Какая версия Symfony выйдет следующей после 8.1 (по состоянию на 07.11.2026)? | «8.2» Пояснение: В Symfony версии выходят последовательно (8.1 -> 8.2 -> 8.3 -> 8.4) до поддержки.
Raw{ ⏎ "answer": "8.2", ⏎ "пояснение": "В Symfony версии выходят последовательно (8.1 -> 8.2 -> 8.3 -> 8.4) до поддержки." ⏎ } | верно | 8.2 — следующий минорный релиз (ноябрь 2026); после его выхода проект переходит с 8.1.* на 8.2.*. |
T29-L4 0.71 c | Symfony: 8.2 и будущее | Symfony 8.2 — мажорный релиз, требующий переписывания приложений под новые API. | «нет» Пояснение: Версия 8.2 не является мажорным релизом Symfony; мажорными релизами являются только целые числа (например, 7.0, 8.0), в то время как .2 обозначает минорный (или патч) релиз.
Raw{ ⏎ "answer": "нет", ⏎ "пояснение": "Версия 8.2 не является мажорным релизом Symfony; мажорными релизами являются только целые числа (например, 7.0, 8.0), в то время как .2 обозначает минорный (или патч) релиз." ⏎ } | верно | Наоборот: 8.2 — минорный релиз; новые возможности без поломки обратной совместимости. Мажор — 9.0. |
T29-L5 0.41 c | Symfony: 8.2 и будущее | Обновление внутри мажорной ветки (8.1 → 8.2) не должно требовать изменений кода — обратная совместимость сохраняется. | «да» Пояснение: В PHP гарантируется, что обновления внутри мажорной версии (например, 8.1 → 8.2) сохраняют обратную совместимость и не требуют изменений кода.
Raw{"answer": "да", "пояснение": "В PHP гарантируется, что обновления внутри мажорной версии (например, 8.1 → 8.2) сохраняют обратную совместимость и не требуют изменений кода."} | верно | Политика Symfony: минорные релизы обратно совместимы; BC-break допустим только в мажорных. |
T29-L6 0.55 c | Symfony: 8.2 и будущее | Какая минорная версия ветки 8.x выйдет последней перед Symfony 9.0? | «8.5» Пояснение: Symfony поддерживает минорные версии в течение 2 лет, а последняя минорная версия перед мажорным обновлением обычно имеет номер 8.5 для ветки 8.x.
Raw{"answer": "8.5", "пояснение": "Symfony поддерживает минорные версии в течение 2 лет, а последняя минорная версия перед мажорным обновлением обычно имеет номер 8.5 для ветки 8.x."} | неверно верный: «8.4» | По циклу: 8.2 (ноя 2026), 8.3 (май 2027), 8.4 (ноя 2027, вместе с 9.0) — как 6.4 выходила вместе с 7.0. |
T29-L7 0.35 c | Symfony: 8.2 и будущее | Symfony 8.2 потребует обновления PHP до 8.5 — придётся обновлять PHP вместе с ней. | «нет» Пояснение: Symfony 8.2 потребует PHP 8.2 или выше, а не 8.5.
Raw{ ⏎ "answer": "нет", ⏎ "пояснение": "Symfony 8.2 потребует PHP 8.2 или выше, а не 8.5." ⏎ } | верно | Наоборот: минорные релизы не поднимают требования PHP; для всей ветки 8.x остаётся PHP >= 8.4. |
T29-L8 0.57 c | Symfony: 8.2 и будущее | Deprecations, добавленные в ветке 8.x, будут удалены не раньше Symfony 9.0. | «да» Пояснение: Symfony следует правилам обратной совместимости, согласно которым несовместимые изменения и удаление deprecated-кода, введенного в мажорных версиях (8.x), откладываются до следующей мажорной версии (9.0).
Raw{"answer": "да", "пояснение": "Symfony следует правилам обратной совместимости, согласно которым несовместимые изменения и удаление deprecated-кода, введенного в мажорных версиях (8.x), откладываются до следующей мажорной версии (9.0)."} | верно | Политика: деприкейшены живут до следующего мажора; 9.0 — ноябрь 2027. |
T21-L1 0.48 c | Twig | Внутри {{ }} в Twig можно вызывать произвольный PHP-код напрямую. | «нет» Пояснение: Twig является системой шаблонов, которая не позволяет напрямую выполнять произвольный PHP-код внутри тегов, чтобы обеспечить безопасность и изоляцию логики представления от кода приложения.
Raw{"answer": "нет", "пояснение": "Twig является системой шаблонов, которая не позволяет напрямую выполнять произвольный PHP-код внутри тегов, чтобы обеспечить безопасность и изоляцию логики представления от кода приложения."} | верно | Twig — DSL: только разрешённые окружением функции/фильтры; произвольный PHP не исполняется. |
T21-L2 0.33 c | Twig | Twig по умолчанию автоматически экранирует выводимые переменные. | «да» Пояснение: Twig по умолчанию применяет автоматическое экранирование (autoescape) для вывода переменных для предотвращения XSS.
Raw{"answer": "да", "пояснение": "Twig по умолчанию применяет автоматическое экранирование (autoescape) для вывода переменных для предотвращения XSS."} | верно | Autoescape включён по умолчанию; {{ '<b>' }} → <b>. Проверено на Twig 3.30. |
T21-L3 0.27 c | Twig | Фильтр |e в Twig экранирует строку для безопасного вывода в HTML-контексте. | «да» Пояснение: Фильтр e в Twig вызывает htmlspecialchars для экранирования HTML-сущностей.
Raw{"answer": "да", "пояснение": "Фильтр e в Twig вызывает htmlspecialchars для экранирования HTML-сущностей."} | верно | |e ('html') по умолчанию; есть контексты js/url/css. От SQL-инъекций он не защищает — это задача подготовленных запросов Doctrine. |
T21-L4 0.28 c | Twig | Какой фильтр из twig/intl-extra форматирует число с учётом локали? | «number_format» Пояснение: Фильтр number_format из twig/intl-extra форматирует число в соответствии с заданной локалью.
Raw{"answer": "number_format", "пояснение": "Фильтр number_format из twig/intl-extra форматирует число в соответствии с заданной локалью."} | неверно верный: «format_number» | |format_number(locale=...) из IntlExtension (twig/intl-extra есть в проекте). Проверено на Twig 3.30: 12345.6 → 12 345,6 (ru). |
T21-L5 0.34 c | Twig | Фильтр |raw отключает автоэкранирование для значения. | «да» Пояснение: Фильтр raw в Blade (Laravel) действительно отключает автоматическое экранирование вывода.
Raw{"answer": "да", "пояснение": "Фильтр raw в Blade (Laravel) действительно отключает автоматическое экранирование вывода."} | верно | {{ x|raw }} выводит HTML как есть; опасно с пользовательскими данными. Проверено на Twig 3.30. |
T21-L6 0.36 c | Twig | В Twig {{ }} выводит значение выражения, а {% %} выполняет теги — условия, циклы, set. | «да» Пояснение: В Twig {{ }} действительно используется для вывода значения выражения, а {% %} — для выполнения структурных тегов, таких как if, for и set.
Raw{"answer": "да", "пояснение": "В Twig {{ }} действительно используется для вывода значения выражения, а {% %} — для выполнения структурных тегов, таких как if, for и set."} | верно | Два блока синтаксиса Twig: вывод (echo) против логики. |
T21-L7 0.29 c | Twig | В Twig нельзя объявить переменную в шаблоне — значения только передаются из контроллера. | «нет» Пояснение: В Twig можно объявлять переменные с помощью тега {% set %}.
Raw{"answer": "нет", "пояснение": "В Twig можно объявлять переменные с помощью тега {% set %}."} | верно | {% set y = ... %} объявляет переменную в шаблоне. Проверено на Twig 3.30. |
T21-L8 0.31 c | Twig | Какая функция Twig выводит отладочную структуру переменной (массива, объекта)? | «dump» Пояснение: Функция dump в Twig используется для вывода отладочной информации о структуре переменной.
Raw{"answer": "dump", "пояснение": "Функция dump в Twig используется для вывода отладочной информации о структуре переменной."} | верно | {{ dump(x) }} (DebugExtension; в Symfony доступна в dev-окружении). |
T24-L1 0.47 c | Bootstrap | Bootstrap — это CSS/JS-библиотека готовых компонентов интерфейса, а не SPA-фреймворк. | «да» Пояснение: Bootstrap представляет собой фреймворк для создания адаптивных веб-интерфейсов на основе CSS и JavaScript, а не полноценный фреймворк для одностраничных приложений (SPA).
Raw{"answer": "да", "пояснение": "Bootstrap представляет собой фреймворк для создания адаптивных веб-интерфейсов на основе CSS и JavaScript, а не полноценный фреймворк для одностраничных приложений (SPA)."} | верно | Компоненты и утилиты поверх вашего HTML; SPA-фреймворки (React/Vue) — другой класс инструментов. В проекте vendored 5.3.3. |
T24-L2 0.37 c | Bootstrap | Какой класс Bootstrap задаёт адаптивный контейнер с фиксированной максимальной шириной по брейкпоинтам? | «container» Пояснение: Класс .container создаёт адаптивный блок с фиксированной максимальной шириной, меняющейся на каждом брейкпоинте.
Raw{"answer": "container", "пояснение": "Класс .container создаёт адаптивный блок с фиксированной максимальной шириной, меняющейся на каждом брейкпоинте."} | верно | .container (фиксированная макс-ширина по брейкпоинтам) vs .container-fluid (на всю ширину). |
T24-L3 0.46 c | Bootstrap | Сетка Bootstrap построена на CSS float и делит строку на 16 колонок. | «нет» Пояснение: Сетка Bootstrap построена на CSS flexbox (начиная с версии 3) и делит строку на 12 колонок, а не 16.
Raw{"answer": "нет", "пояснение": "Сетка Bootstrap построена на CSS flexbox (начиная с версии 3) и делит строку на 12 колонок, а не 16."} | верно | Наоборот: flexbox (с Bootstrap 4) и 12 колонок; float-сетка — это Bootstrap 3. |
T24-L4 0.32 c | Bootstrap | Именованные брейкпоинты Bootstrap (с инфиксом в классах) — sm, md, lg, xl, xxl; их пять. | «да» Пояснение: Bootstrap 5 включает пять именованных брейкпоинтов: sm, md, lg, xl и xxl.
Raw{"answer": "да", "пояснение": "Bootstrap 5 включает пять именованных брейкпоинтов: sm, md, lg, xl и xxl."} | верно | Тиров всего шесть: xs (без инфикса) + пять именованных (576/768/992/1200/1400 px). |
T24-L5 0.58 c | Bootstrap | Утилиты вроде .mt-3 или .px-2 используют шаг spacing-шкалы: число — множитель $spacer. | «да» Пояснение: В Tailwind CSS значения утилит отступов и размеров (mt, px и т.д.) действительно рассчитываются как произведение индекса на базовое значение $spacer (по умолчанию 1rem).
Raw{"answer": "да", "пояснение": "В Tailwind CSS значения утилит отступов и размеров (mt, px и т.д.) действительно рассчитываются как произведение индекса на базовое значение $spacer (по умолчанию 1rem)."} | неверно верный: «нет» | Число — ключ карты $spacers (1→0.25rem, 2→0.5rem, 3→1rem, 4→1.5rem, 5→3rem), не множитель: .mt-3 = 1rem = $spacer, .mt-5 = 3rem = $spacer×3 (машинно: bootstrap.css 5.3.3). |
T24-L6 0.39 c | Bootstrap | Какой data-атрибут Bootstrap 5 включает интерактивный компонент (например, dropdown) на элементе? | «data-bs-toggle» Пояснение: В Bootstrap 5 для инициализации интерактивных компонентов, таких как dropdown или popover, используется атрибут data-bs-toggle.
Raw{"answer": "data-bs-toggle", "пояснение": "В Bootstrap 5 для инициализации интерактивных компонентов, таких как dropdown или popover, используется атрибут data-bs-toggle."} | верно | data-bs-toggle="dropdown" и т.п.; в Bootstrap 4 атрибут назывался data-toggle. |
T24-L7 0.39 c | Bootstrap | Компоненты Bootstrap 5 работают без jQuery — на чистом vanilla JS. | «да» Пояснение: Bootstrap 5 полностью отказался от зависимости от jQuery и использует нативный JavaScript для работы своих компонентов.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Bootstrap 5 полностью отказался от зависимости от jQuery и использует нативный JavaScript для работы своих компонентов." ⏎ } | верно | jQuery удалён в Bootstrap 5.0: data-bs-* атрибуты и JS API. В проекте vendored 5.3.3. |
T24-L8 0.33 c | Bootstrap | Тёмную тему в Bootstrap включают классом .dark на корневом элементе. | «нет» Пояснение: Для включения тёмной темы в Bootstrap 5 используется атрибут data-bs-theme="dark", а не класс .dark.
Raw{"answer": "нет", "пояснение": "Для включения тёмной темы в Bootstrap 5 используется атрибут data-bs-theme=\"dark\", а не класс .dark."} | верно | Наоборот: тема включается атрибутом data-bs-theme="dark" (Color modes, с 5.3); класса .dark не существует. В проекте 5.3.3. |
T14-L1 0.41 c | Doctrine | Doctrine ORM сам создаёт таблицы в базе при первом обращении к сущности в рантайме. | «нет» Пояснение: Doctrine ORM не создает таблицы автоматически в рантайме; для этого необходимо использовать миграции (через DoctrineMigrations) или утилиту schema-tool.
Raw{"answer": "нет", "пояснение": "Doctrine ORM не создает таблицы автоматически в рантайме; для этого необходимо использовать миграции (через DoctrineMigrations) или утилиту schema-tool."} | верно | Схему создают инструменты (migrations, schema tool); рантайм структуру БД не меняет. |
T14-L2 0.44 c | Doctrine | Какой метод EntityManager помечает новый объект как управляемый, не выполняя SQL до flush()? | «persist» Пояснение: Метод persist() добавляет объект в менеджер сущностей и помечает его для вставки при выполнении flush(), не генерируя SQL немедленно.
Raw{"answer": "persist", "пояснение": "Метод persist() добавляет объект в менеджер сущностей и помечает его для вставки при выполнении flush(), не генерируя SQL немедленно."} | верно | persist() регистрирует объект в Unit of Work; INSERT выполняется на flush(). |
T14-L3 0.48 c | Doctrine | В Doctrine ORM 3 метод EntityManager::merge() доступен и делает переданный объект управляемым. | «нет» Пояснение: Метод EntityManager::merge() был удалён в Doctrine ORM 3, его функциональность теперь обеспечивается методом persist() или повторным использованием уже управляемого экземпляра.
Raw{"answer": "нет", "пояснение": "Метод EntityManager::merge() был удалён в Doctrine ORM 3, его функциональность теперь обеспечивается методом persist() или повторным использованием уже управляемого экземпляра."} | верно | В ORM 3 merge() удалён (в vendor проекта 3.7.6 метода нет); в Doctrine 2.x merge() возвращал управляемую копию. Версия зафиксирована — ORM 3. |
T14-L4 0.34 c | Doctrine | DQL-запросы пишутся в терминах сущностей и их полей, а не таблиц и столбцов. | «да» Пояснение: DQL (Doctrine Query Language) оперирует сущностями и их полями, а не с физическими таблицами и столбцами базы данных.
Raw{"answer": "да", "пояснение": "DQL (Doctrine Query Language) оперирует сущностями и их полями, а не с физическими таблицами и столбцами базы данных."} | верно | Doctrine транслирует DQL в SQL; docs — DQL (Doctrine Query Language). |
T14-L5 0.3 c | Doctrine | Что вернёт $repository->find(999), если записи с идентификатором 999 нет? | «нет» Пояснение: Метод find() возвращает null, если сущность с указанным идентификатором не найдена.
Raw{"answer": "нет", "пояснение": "Метод find() возвращает null, если сущность с указанным идентификатором не найдена."} | неверно верный: «null» | find() возвращает null, если объект не найден (docs Repository methods). |
T14-L6 0.68 c | Doctrine | DoctrineBundle в Symfony автоматически вызывает flush() в конце каждого запроса. | «нет» Пояснение: Symfony/Doctrine не выполняет автоматический flush в конце каждого HTTP-запроса по умолчанию, если только это не настроено вручную или не используется специфичный middleware/bundle, так как стандартное поведение требует явного вызова flush().
Raw{ ⏎ "answer": "нет", ⏎ "пояснение": "Symfony/Doctrine не выполняет автоматический flush в конце каждого HTTP-запроса по умолчанию, если только это не настроено вручную или не используется специфичный middleware/bundle, так как стандартное поведение требует явного вызова flush()." ⏎ } | верно | Авто-flush нет — flush() зовёт разработчик; незакрытая транзакция в конце запроса откатывается. |
T14-L7 0.4 c | Doctrine | Для управляемой сущности достаточно изменить свойство: flush() зафиксирует изменение без вызова persist() — Unit of Work отслеживает изменения. | «да» Пояснение: Unit of Work отслеживает изменения свойств у уже управляемых сущностей, поэтому для сохранения изменений достаточно вызвать flush().
Raw{"answer": "да", "пояснение": "Unit of Work отслеживает изменения свойств у уже управляемых сущностей, поэтому для сохранения изменений достаточно вызвать flush()."} | верно | Dirty checking сравнивает снимки свойств; persist нужен только новым/отсоединённым объектам. |
T14-L8 0.42 c | Doctrine | remove() выполняет SQL DELETE сразу, не дожидаясь flush(). | «нет» Пояснение: В ORM (например, Doctrine) метод remove() помечает сущность для удаления, но SQL запрос DELETE выполняется только при вызове flush() или commit().
Raw{"answer": "нет", "пояснение": "В ORM (например, Doctrine) метод remove() помечает сущность для удаления, но SQL запрос DELETE выполняется только при вызове flush() или commit()."} | верно | remove() планирует удаление в Unit of Work; DELETE выполняется на flush() (docs — Deleting Objects). |
T15-L1 0.36 c | PostgreSQL | PostgreSQL использует MVCC, поэтому читатели блокируют писателей, а писатели — читателей. | «нет» Пояснение: MVCC позволяет читателям и писателям работать параллельно без блокировок друг друга (читатели не блокируют писателей, а писатели не блокируют читателей).
Raw{"answer": "нет", "пояснение": "MVCC позволяет читателям и писателям работать параллельно без блокировок друг друга (читатели не блокируют писателей, а писатели не блокируют читателей)."} | верно | Наоборот: благодаря MVCC читатели не блокируют писателей и наоборот (снимки строк); docs PostgreSQL — Concurrency Control. |
T15-L2 0.26 c | PostgreSQL | Какая команда SQL показывает план выполнения запроса, не выполняя сам запрос? | «explain» Пояснение: Оператор EXPLAIN показывает план выполнения запроса без его фактического исполнения.
Raw{"answer": "EXPLAIN", "пояснение": "Оператор EXPLAIN показывает план выполнения запроса без его фактического исполнения."} | верно | EXPLAIN без ANALYZE только строит план; проверено на PostgreSQL 17.7. |
T15-L3 0.72 c | PostgreSQL | SERIAL и GENERATED ... AS IDENTITY — это два названия одного и того же механизма. | «нет» Пояснение: Синтаксис GENERATED AS IDENTITY является стандартным и более предпочтительным, а SERIAL — это псевдо-тип PostgreSQL, который развертывается в таблицу, последовательность и триггеры для совместимости со старыми стандартами (MySQL).
Raw{ ⏎ "answer": "нет", ⏎ "пояснение": "Синтаксис GENERATED AS IDENTITY является стандартным и более предпочтительным, а SERIAL — это псевдо-тип PostgreSQL, который развертывается в таблицу, последовательность и триггеры для совместимости со старыми стандартами (MySQL)." ⏎ } | верно | SERIAL — нестандартный макрос (sequence + DEFAULT), IDENTITY — SQL-стандарт; различаются владением и правами. Оба есть в PG 17 (проверено). |
T15-L4 0.59 c | PostgreSQL | UNIQUE-ограничение PostgreSQL по умолчанию допускает только одну строку с NULL в столбце. | «нет» Пояснение: PostgreSQL (как и большинство SQL СУБД) считает значения NULL различающимися, поэтому в столбце с UNIQUE-ограничением можно хранить неограниченное количество строк со значением NULL.
Raw{"answer": "нет", "пояснение": "PostgreSQL (как и большинство SQL СУБД) считает значения NULL различающимися, поэтому в столбце с UNIQUE-ограничением можно хранить неограниченное количество строк со значением NULL."} | верно | Наоборот: NULLS DISTINCT по умолчанию — несколько NULL допустимы; NULLS NOT DISTINCT — опция с PG 15. Проверено на PG 17.7. |
T15-L5 0.38 c | PostgreSQL | Какая агрегатная функция PostgreSQL склеивает строки с разделителем? | «string_agg» Пояснение: Функция string_agg(col, delimiter) агрегирует строки, склеивая их с указанным разделителем.
Raw{"answer": "string_agg", "пояснение": "Функция string_agg(col, delimiter) агрегирует строки, склеивая их с указанным разделителем."} | верно | string_agg(значение, разделитель); проверено на PostgreSQL 17.7. |
T15-L6 0.4 c | PostgreSQL | Обычный VACUUM возвращает место, занятое «мёртвыми» кортежами, операционной системе. | «нет» Пояснение: Обычный VACUUM только освобождает пространство для повторного использования внутри базы данных, возвращая место операционной системе может лишь VACUUM FULL.
Raw{"answer": "нет", "пояснение": "Обычный VACUUM только освобождает пространство для повторного использования внутри базы данных, возвращая место операционной системе может лишь VACUUM FULL."} | верно | VACUUM помечает место для переиспользования внутри таблицы; ОС его возвращает только VACUUM FULL (с эксклюзивной блокировкой). |
T15-L7 0.49 c | PostgreSQL | Какое ключевое слово в определении window-функции разбивает строки на группы, для которых считается функция? | «partition by» Пояснение: Ключевое слово PARTITION BY в window-функции разбивает данные на группы, внутри которых выполняется агрегация или вычисление.
Raw{"answer": "PARTITION BY", "пояснение": "Ключевое слово PARTITION BY в window-функции разбивает данные на группы, внутри которых выполняется агрегация или вычисление."} | верно | OVER (PARTITION BY ...); проверено на PostgreSQL 17.7. |
T15-L8 0.41 c | PostgreSQL | Уровень изоляции READ COMMITTED защищает от неповторяющегося чтения (non-repeatable read). | «нет» Пояснение: Уровень READ COMMITTED защищает от грязного чтения, но допускает неповторяющееся чтение и фантомные записи.
Raw{ ⏎ "answer": "нет", ⏎ "пояснение": "Уровень READ COMMITTED защищает от грязного чтения, но допускает неповторяющееся чтение и фантомные записи." ⏎ } | верно | READ COMMITTED допускает неповторяющееся чтение; защищает REPEATABLE READ. Проверено: SHOW transaction_isolation → read committed. |
T17-L1 0.32 c | PostgreSQL: транзакции и индексы | По умолчанию PostgreSQL выполняет каждый отдельный SQL-оператор в собственной неявной транзакции (autocommit). | «да» Пояснение: По умолчанию PostgreSQL действительно работает в режиме autocommit, автоматически завершая транзакцию после каждой SQL-команды.
Raw{"answer": "да", "пояснение": "По умолчанию PostgreSQL действительно работает в режиме autocommit, автоматически завершая транзакцию после каждой SQL-команды."} | верно | Без BEGIN каждый оператор коммитится сам; docs PostgreSQL — Transactions. Проверено на PG 17. |
T17-L2 0.24 c | PostgreSQL: транзакции и индексы | Какая SQL-команда завершает транзакцию, сохраняя все её изменения? | «commit» Пояснение: Команда COMMIT фиксирует изменения транзакции в базе данных.
Raw{"answer": "COMMIT", "пояснение": "Команда COMMIT фиксирует изменения транзакции в базе данных."} | верно | COMMIT (END — синоним). Проверено на PG 17. |
T17-L3 0.28 c | PostgreSQL: транзакции и индексы | Индексы ускоряют не только SELECT: UPDATE и DELETE с поиском по индексированному столбцу тоже выигрывают. | «да» Пояснение: Индексы ускоряют нахождение строк для UPDATE и DELETE так же, как и для SELECT.
Raw{"answer": "да", "пояснение": "Индексы ускоряют нахождение строк для UPDATE и DELETE так же, как и для SELECT."} | верно | Поиск строк для изменения идёт по индексу; docs PostgreSQL — Indexes. |
T17-L4 0.33 c | PostgreSQL: транзакции и индексы | Для отката части операторов внутри транзакции PostgreSQL использует SAVEPOINT. | «да» Пояснение: SAVEPOINT позволяет откатить транзакцию до определённой точки без отмены всей транзакции.
Raw{"answer": "да", "пояснение": "SAVEPOINT позволяет откатить транзакцию до определённой точки без отмены всей транзакции."} | верно | SAVEPOINT name; ROLLBACK TO name — частичный откат без отмены всей транзакции. Проверено на PG 17. |
T17-L5 0.38 c | PostgreSQL: транзакции и индексы | EXPLAIN ANALYZE показывает план запроса, не выполняя сам запрос. | «нет» Пояснение: EXPLAIN ANALYZE (или EXPLAIN BUFFERS) выполняет запрос и показывает фактическое время выполнения, в отличие от обычного EXPLAIN.
Raw{"answer": "нет", "пояснение": "EXPLAIN ANALYZE (или EXPLAIN BUFFERS) выполняет запрос и показывает фактическое время выполнения, в отличие от обычного EXPLAIN."} | верно | Наоборот: ANALYZE реально выполняет запрос (с побочными эффектами!) и показывает фактические времена узлов; план без выполнения — plain EXPLAIN. |
T17-L6 0.32 c | PostgreSQL: транзакции и индексы | Какое расширение PostgreSQL добавляет векторные типы и индексы для поиска по эмбеддингам? | «pgvector» Пояснение: Расширение pgvector добавляет в PostgreSQL поддержку векторных типов данных и индексов для эффективного поиска по эмбеддингам.
Raw{"answer": "pgvector", "пояснение": "Расширение pgvector добавляет в PostgreSQL поддержку векторных типов данных и индексов для эффективного поиска по эмбеддингам."} | верно | CREATE EXTENSION vector (проект pgvector; в проекте образ pgvector/pgvector:pg17). |
T17-L7 0.36 c | PostgreSQL: транзакции и индексы | Частичный индекс (CREATE INDEX ... WHERE ...) строится только по строкам, удовлетворяющим условию. | «да» Пояснение: Частичные индексы в PostgreSQL создаются только для строк, которые удовлетворяют заданному условию WHERE.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "Частичные индексы в PostgreSQL создаются только для строк, которые удовлетворяют заданному условию WHERE." ⏎ } | верно | docs PostgreSQL — Partial Indexes; типичный кейс — индекс по «активным» записям. |
T17-L8 0.66 c | PostgreSQL: транзакции и индексы | Уровень SERIALIZABLE в PostgreSQL реализован блокировкой строк, которые читает транзакция. | «нет» Пояснение: Уровень SERIALIZABLE в PostgreSQL реализует механизм проверки конфликтов транзакций (predicate locking или SSI), а не простое блокирование читаемых строк (что характерно для REPEATABLE READ или более низких уровней).
Raw{ ⏎ "answer": "нет", ⏎ "пояснение": "Уровень SERIALIZABLE в PostgreSQL реализует механизм проверки конфликтов транзакций (predicate locking или SSI), а не простое блокирование читаемых строк (что характерно для REPEATABLE READ или более низких уровней)." ⏎ } | верно | SSI (Serializable Snapshot Isolation): предикатные блокировки на снимках, не блокировки прочитанных строк; docs PostgreSQL. |
T19-L1 0.32 c | HTTP и REST API | HTTP-статус 201 означает, что в результате запроса создан новый ресурс. | «да» Пояснение: HTTP-статус 201 (Created) используется для подтверждения успешного создания нового ресурса.
Raw{"answer": "да", "пояснение": "HTTP-статус 201 (Created) используется для подтверждения успешного создания нового ресурса."} | верно | 201 Created; обычно на POST, часто с Location; RFC 9110. |
T19-L2 0.38 c | HTTP и REST API | Какой HTTP-статус означает успешный запрос с пустым телом ответа (например, после DELETE)? | «204» Пояснение: HTTP-статус 204 No Content используется для указания, что сервер успешно обработал запрос, но не возвращает тело ответа.
Raw{"answer": 204, "пояснение": "HTTP-статус 204 No Content используется для указания, что сервер успешно обработал запрос, но не возвращает тело ответа."} | верно | 204 No Content; RFC 9110. |
T19-L3 0.36 c | HTTP и REST API | Метод DELETE идемпотентен по спецификации HTTP: повторный запрос по тому же ресурсу не меняет результат. | «да» Пояснение: Согласно спецификации HTTP, метод DELETE является идемпотентным, так как повторное удаление одного и того же ресурса не приводит к изменению состояния сервера.
Raw{"answer": "да", "пояснение": "Согласно спецификации HTTP, метод DELETE является идемпотентным, так как повторное удаление одного и того же ресурса не приводит к изменению состояния сервера."} | верно | RFC 9110: DELETE идемпотентен (как PUT); идемпотентность ≠ безопасность — ресурс удаляется при первом вызове. |
T19-L4 0.35 c | HTTP и REST API | Заголовок Access-Control-Allow-Origin отправляет клиент, чтобы сервер разрешил принимать запросы с другого origin. | «нет» Пояснение: Заголовок Access-Control-Allow-Origin отправляет сервер в ответе на запрос браузера, а не клиент.
Raw{"answer": "нет", "пояснение": "Заголовок Access-Control-Allow-Origin отправляет сервер в ответе на запрос браузера, а не клиент."} | верно | Наоборот: заголовок шлёт СЕРВЕР в ответе, разрешая браузеру cross-origin запрос (CORS); в проекте nelmio/cors-bundle. |
T19-L5 0.31 c | HTTP и REST API | Код 429 Too Many Requests используется, когда клиент превысил лимит запросов (rate limiting). | «да» Пояснение: Код 429 предназначен для информирования клиента о превышении лимита частоты запросов.
Raw{"answer": "да", "пояснение": "Код 429 предназначен для информирования клиента о превышении лимита частоты запросов."} | верно | 429 (+ Retry-After); RFC 6585. В проекте symfony/rate-limiter. |
T19-L6 0.29 c | HTTP и REST API | Коды 5xx означают ошибку клиента, а 4xx — ошибку на стороне сервера. | «нет» Пояснение: Коды 4xx указывают на ошибку клиента, а 5xx — на ошибку сервера.
Raw{"answer": "нет", "пояснение": "Коды 4xx указывают на ошибку клиента, а 5xx — на ошибку сервера."} | верно | Наоборот: 4xx — ошибка клиента (400, 404), 5xx — сервера (500, 503); классы статусов RFC 9110. |
T19-L7 0.35 c | HTTP и REST API | Какой HTTP-заголовок указывает MIME-тип тела запроса или ответа? | «content-type» Пояснение: Заголовок Content-Type указывает тип контента (MIME-тип) для тела HTTP-запроса или ответа.
Raw{"answer": "Content-Type", "пояснение": "Заголовок Content-Type указывает тип контента (MIME-тип) для тела HTTP-запроса или ответа."} | верно | Content-Type: application/json и т.п. |
T19-L8 0.38 c | HTTP и REST API | PATCH не обязан быть идемпотентным по RFC 5789, в отличие от PUT. | «да» Пояснение: Согласно RFC 5789, PATCH не является идемпотентным по определению, тогда как PUT должен быть идемпотентным.
Raw{"answer": "да", "пояснение": "Согласно RFC 5789, PATCH не является идемпотентным по определению, тогда как PUT должен быть идемпотентным."} | верно | RFC 5789 прямо оговаривает: PATCH не гарантированно идемпотентен; PUT идемпотентен. |
T20-L1 0.51 c | Безопасность и OAuth | Проверить пароль достаточно сравнением его хеша с хешем из базы обычным оператором ==. | «нет» Пояснение: Сравнение хешей паролей должно выполняться функцией hash_equals для защиты от атак по времени (timing attacks), так как обычный оператор == не является constant-time.
Raw{"answer": "нет", "пояснение": "Сравнение хешей паролей должно выполняться функцией hash_equals для защиты от атак по времени (timing attacks), так как обычный оператор == не является constant-time."} | верно | Нужна постоянновременная проверка (password_verify) — timing-атаки; соль и алгоритм уже внутри хеша. |
T20-L2 0.5 c | Безопасность и OAuth | CSRF-токен выдаётся сервером (привязан к сессии) и проверяется на сервере при unsafe-запросах (POST и т.п.). | «да» Пояснение: CSRF-токен генерируется сервером, хранится в сессии и проверяется на сервере при обработке небезопасных запросов, чтобы убедиться, что запрос исходит от подлинного пользователя.
Raw{ ⏎ "answer": "да", ⏎ "пояснение": "CSRF-токен генерируется сервером, хранится в сессии и проверяется на сервере при обработке небезопасных запросов, чтобы убедиться, что запрос исходит от подлинного пользователя." ⏎ } | верно | symfony/security-csrf в проекте; защита от подделки межсайтовой формы. |
T20-L3 0.31 c | Безопасность и OAuth | Какой HTTP-заголовок включает политику CSP (Content Security Policy)? | «content-security-policy» Пояснение: Политика CSP передается в HTTP-заголовке с именем Content-Security-Policy.
Raw{"answer": "Content-Security-Policy", "пояснение": "Политика CSP передается в HTTP-заголовке с именем Content-Security-Policy."} | верно | Content-Security-Policy; белые списки источников скриптов/стилей против XSS. |
T20-L4 0.38 c | Безопасность и OAuth | OAuth 2.0 — протокол аутентификации: access-токен сообщает, кто именно пользователь. | «нет» Пояснение: OAuth 2.0 — это протокол авторизации (делегирования доступа), а не аутентификации (определения личности).
Raw{"answer": "нет", "пояснение": "OAuth 2.0 — это протокол авторизации (делегирования доступа), а не аутентификации (определения личности)."} | верно | OAuth 2.0 — авторизация/делегирование доступа; аутентификацию добавляет OpenID Connect. В проекте knpuniversity/oauth2-client-bundle (yandex/github/google). |
T20-L5 0.31 c | Безопасность и OAuth | XSS предотвращается валидацией ввода на сервере перед записью в базу. | «нет» Пояснение: XSS предотвращается экранированием вывода при рендеринге, а не только валидацией при записи.
Raw{"answer": "нет", "пояснение": "XSS предотвращается экранированием вывода при рендеринге, а не только валидацией при записи."} | верно | XSS лечится контекстным экранированием НА ВЫВОДЕ (Twig autoescape, CSP); валидация ввода не покрывает все контексты вывода. |
T20-L6 0.3 c | Безопасность и OAuth | В authorization code flow OAuth 2.0 какой параметр приходит в redirect_uri и обменивается на access-токен? | «code» Пояснение: В authorization code flow в redirect_uri приходит параметр code, который затем обменивается на access-токен.
Raw{"answer": "code", "пояснение": "В authorization code flow в redirect_uri приходит параметр code, который затем обменивается на access-токен."} | верно | Параметр code; обмен на токен POST-ом на /token с client_secret. |
T20-L7 0.36 c | Безопасность и OAuth | Refresh-токен живёт дольше access-токена и позволяет получить новый access-токен без повторного входа пользователя. | «да» Пояснение: Refresh-токен действительно имеет больший срок действия и используется для обновления просроченного access-токена без повторной аутентификации.
Raw{"answer": "да", "пояснение": "Refresh-токен действительно имеет больший срок действия и используется для обновления просроченного access-токена без повторной аутентификации."} | верно | Стандартная схема OAuth/OIDC: короткий access + длинный refresh. |
T20-L8 0.31 c | Безопасность и OAuth | Соль пароля нужно держать в секрете: без неё хеш нельзя проверить. | «нет» Пояснение: Соль является открытой информацией и должна храниться вместе с хешем, чтобы можно было проверить пароль при входе.
Raw{"answer": "нет", "пояснение": "Соль является открытой информацией и должна храниться вместе с хешем, чтобы можно было проверить пароль при входе."} | верно | Соль хранится открыто (password_hash включает её в строку хеша); секретность соли не нужна. |
T18-L1 0.33 c | Тестирование: PHPUnit | PHPUnit выполняет тестовые методы любого класса — наследовать TestCase не обязательно. | «нет» Пояснение: PHPUnit требует, чтобы тестовые классы наследовались от PHPUnit\Framework\TestCase для использования его функциональности.
Raw{"answer": "нет", "пояснение": "PHPUnit требует, чтобы тестовые классы наследовались от PHPUnit\\Framework\\TestCase для использования его функциональности."} | верно | Тестом считается метод класса, наследующего TestCase (PHPUnit 10). |
T18-L2 0.3 c | Тестирование: PHPUnit | Метод setUp() в PHPUnit вызывается один раз перед всеми тестами класса. | «нет» Пояснение: setUp() вызывается перед каждым тестом, а setUpBeforeClass() — один раз перед всеми тестами класса.
Raw{"answer": "нет", "пояснение": "setUp() вызывается перед каждым тестом, а setUpBeforeClass() — один раз перед всеми тестами класса."} | верно | setUp() — перед КАЖДЫМ тестом; один раз на класс — setUpBeforeClass(). Проверено живым счётчиком на PHPUnit 10.5. |
T18-L3 0.3 c | Тестирование: PHPUnit | Поставщик данных (data provider) позволяет прогнать тест ровно с одним набором аргументов. | «нет» Пояснение: Data provider позволяет прогнать тест с несколькими наборами аргументов, а не только с одним.
Raw{"answer": "нет", "пояснение": "Data provider позволяет прогнать тест с несколькими наборами аргументов, а не только с одним."} | верно | Наоборот: наборов может быть сколько угодно — тест выполняется по разу на каждый. Проверено на PHPUnit 10.5 (#[DataProvider]). |
T18-L4 0.25 c | Тестирование: PHPUnit | Какой метод PHPUnit объявляет ожидание исключения определённого класса? | «expectexception» Пояснение: Метод expectException() в PHPUnit используется для ожидания исключения конкретного класса.
Raw{"answer": "expectException", "пояснение": "Метод expectException() в PHPUnit используется для ожидания исключения конкретного класса."} | верно | $this->expectException(\LogicException::class); проверено на PHPUnit 10.5. |
T18-L5 0.39 c | Тестирование: PHPUnit | В PHPUnit стаб (stub) проверяет, какие методы на нём вызывали, а мок (mock) только подставляет данные. | «нет» Пояснение: Определения перепутаны: мок (mock) проверяет вызовы методов, а стаб (stub) только подставляет данные (возвратные значения).
Raw{"answer": "нет", "пояснение": "Определения перепутаны: мок (mock) проверяет вызовы методов, а стаб (stub) только подставляет данные (возвратные значения)."} | верно | Наоборот: стаб подставляет данные, мок проверяет взаимодействия (createStub/createMock); docs PHPUnit — Test Doubles. |
T18-L6 0.55 c | Тестирование: PHPUnit | В PHPUnit 10+ рекомендуемый способ передачи данных в тест — атрибут #[DataProvider] (аннотация @dataProvider устарела). | «да» Пояснение: В PHPUnit 10 и выше аннотации PHPDoc (включая @dataProvider) официально объявлены устаревшими, а для передачи данных в методы тестов рекомендуется использовать атрибуты PHP 8, такие как #[DataProvider].
Raw{"answer": "да", "пояснение": "В PHPUnit 10 и выше аннотации PHPDoc (включая @dataProvider) официально объявлены устаревшими, а для передачи данных в методы тестов рекомендуется использовать атрибуты PHP 8, такие как #[DataProvider]."} | верно | Аннотация ещё парсится в PHPUnit 10/11 (AnnotationParser в 10.5.66), удаление — в 12; атрибут — стандарт. |
T18-L7 0.37 c | Тестирование: PHPUnit | В PHPUnit нельзя объявить зависимость одного теста от результата другого. | «нет» Пояснение: В PHPUnit можно использовать атрибуты @depends или метод depends() для объявления зависимостей между тестами.
Raw{ ⏎ "answer": "нет", ⏎ "пояснение": "В PHPUnit можно использовать атрибуты @depends или метод depends() для объявления зависимостей между тестами." ⏎ } | верно | Зависимости есть: #[Depends] — зависимый тест не запустится, еслиProducer упал. |
T18-L8 0.28 c | Тестирование: PHPUnit | Какая опция командной строки PHPUnit включает случайный порядок выполнения тестов? | «--order-by=random» Пояснение: Опция --order-by=random заставляет PHPUnit выполнять тесты в случайном порядке.
Raw{"answer": "--order-by=random", "пояснение": "Опция --order-by=random заставляет PHPUnit выполнять тесты в случайном порядке."} | верно | --order-by=random (PHPUnit 9+); опция есть в --help PHPUnit 10.5 (проектная). |
T01-L9 3.3 c | Синтаксис и операторы | Что выведет этот код?
```php
echo intdiv(7, 2) . intdiv(-7, 2);
``` | «3-4» Пояснение: intdiv(7, 2) возвращает 3, а intdiv(-7, 2) возвращает -4 (округление к минусу бесконечности), что при конкатенации дает строку '3-4'.
Raw{"answer": "3-4", "пояснение": "intdiv(7, 2) возвращает 3, а intdiv(-7, 2) возвращает -4 (округление к минусу бесконечности), что при конкатенации дает строку '3-4'."} | неверно верный: «3-3» | intdiv обрезает к нулю: intdiv(-7, 2) = -3, не -4. |
T01-L10 0.43 c | Синтаксис и операторы | Что выведет этот код?
```php
echo -3 ** 2;
``` | «-9» Пояснение: В PHP оператор возведения в степень (**) имеет более высокий приоритет, чем унарный минус (-), поэтому выражение интерпретируется как -(3 ** 2).
Raw{"answer": -9, "пояснение": "В PHP оператор возведения в степень (**) имеет более высокий приоритет, чем унарный минус (-), поэтому выражение интерпретируется как -(3 ** 2)."} | верно | ** правоассоциативен и связывает крепче унарного минуса: -(3²). |
T02-L9 2.14 c | Типы и сравнения | Что выведет этот код?
```php
echo '1e1' == '10' ? 'true' : 'false';
``` | «false» Пояснение: В PHP 8 при сравнении строки, похожей на научную нотацию ('1e1'), со строкой, похожей на число ('10'), обе интерпретируются как числа (10.0 и 10.0), они равны, поэтому условие верно и выведется 'true' в PHP 7/8 (если бы не было ошибки), но в PHP 8 '1e1' рассматривается как валидное число (10), а '10' как 10, они равны, значит выведется 'true'. Однако, проверим: '1e1' === 10 (true), '10' === 10 (true). 10 == 10 => true. Ответ 'true'. Ошибка в моих размышлениях: код выводит 'true'. Но в вопросе часто ловушка с PHP 8. В PHP 8 '1e1' и '10' при == обе кастируются в float/int. '1e1' -> 10. '10' -> 10. 10 == 10 -> true. Выводится 'true'.
Raw{"answer": "false", "пояснение": "В PHP 8 при сравнении строки, похожей на научную нотацию ('1e1'), со строкой, похожей на число ('10'), обе интерпретируются как числа (10.0 и 10.0), они равны, поэтому условие верно и выведется 'true' в PHP 7/8 (если бы не было ошибки), но в PHP 8 '1e1' рассматривается как валидное число (10), а '10' как 10, они равны, значит выведется 'true'. Однако, проверим: '1e1' === 10 (true), '10' === 10 (true). 10 == 10 => true. Ответ 'true'. Ошибка в моих размышлениях: код выводит 'true'. Но в вопросе часто ловушка с PHP 8. В PHP 8 '1e1' и '10' при == обе кастируются в float/int. '1e1' -> 10. '10' -> 10. 10 == 10 -> true. Выводится 'true'."} | неверно верный: «true» | Обе строки числовые — сравнение как чисел: 10 == 10. |
T02-L10 0.41 c | Типы и сравнения | Что выведет этот код?
```php
switch ('a') {
case 0: echo 'zero'; break;
default: echo 'other';
}
``` | «other» Пояснение: Сравнение 'a' с 0 использует слабое сравнение, где строка 'a' не равна нулю, поэтому выполняется ветка default.
Raw{"answer": "other", "пояснение": "Сравнение 'a' с 0 использует слабое сравнение, где строка 'a' не равна нулю, поэтому выполняется ветка default."} | верно | PHP 8: 'a' == 0 → false (раньше было true) — срабатывает default. |
T03-L9 0.4 c | Строки | Что выведет этот код?
```php
echo strtr('abc', ['a' => '1', 'ab' => '2']);
``` | «2bc» Пояснение: strtr заменяет более длинные ключи раньше: 'ab' -> '2', 'a' -> '1', итог '2bc'.
Raw{"answer": "2bc", "пояснение": "strtr заменяет более длинные ключи раньше: 'ab' -> '2', 'a' -> '1', итог '2bc'."} | неверно верный: «2c» | strtr с массивом предпочитает самое длинное совпадение ключа. |
T03-L10 0.32 c | Строки | Что выведет этот код?
```php
echo '[' . substr('hello', -10) . ']';
``` | «[hello]» Пояснение: Функция substr возвращает всю строку, если смещение превышает её длину в отрицательную сторону.
Raw{"answer": "[hello]", "пояснение": "Функция substr возвращает всю строку, если смещение превышает её длину в отрицательную сторону."} | верно | Отрицательный старт за пределами строки зажимается к началу. |
T04-L9 0.48 c | Массивы | Что выведет этот код?
```php
$a = ['k' => 1, 'n' => 2];
$b = ['k' => 9, 'm' => 3];
echo implode(',', array_keys($a + $b));
``` | «k,n,m» Пояснение: Оператор + объединяет массивы, оставляя значения из левого массива ($a) для повторяющихся ключей, поэтому результат array_keys — ['k', 'n', 'm']
Raw{"answer": "k,n,m", "пояснение": "Оператор + объединяет массивы, оставляя значения из левого массива ($a) для повторяющихся ключей, поэтому результат array_keys — ['k', 'n', 'm']"} | верно | Оператор + : при дубликатах строковых ключей побеждает левый массив. |
T04-L10 1.71 c | Массивы | Что выведет этот код?
```php
$a = [[1, 'x', 2], [2, 'y', 1], [3, 'z', 2]];
usort($a, fn($p, $q) => $p[2] <=> $q[2]);
echo implode('', array_column($a, 1));
``` | «xzy» Пояснение: usort сортирует массив по третьему элементу (индекс 2) по возрастанию: сначала [1, 'x', 2] (2), затем [3, 'z', 2] (2) и [2, 'y', 1] (1) — но так как порядок у стабильных сортировок сохраняется для равных значений, фактически порядок будет: [1, 'x', 2], [3, 'z', 2], [2, 'y', 1]? Нет, подожди: usort в PHP 8.0+ является стабильным, но при сравнении 2 и 2 они считаются равными, а 1 меньше 2. Поэтому порядок будет: [2, 'y', 1] (1), [1, 'x', 2] (2), [3, 'z', 2] (2). Тогда array_column($a, 1) даст ['y', 'x', 'z'], implode → 'yxz'.
Raw{"answer": "xzy", "пояснение": "usort сортирует массив по третьему элементу (индекс 2) по возрастанию: сначала [1, 'x', 2] (2), затем [3, 'z', 2] (2) и [2, 'y', 1] (1) — но так как порядок у стабильных сортировок сохраняется для равных значений, фактически порядок будет: [1, 'x', 2], [3, 'z', 2], [2, 'y', 1]? Нет, подожди: usort в PHP 8.0+ является стабильным, но при сравнении 2 и 2 они считаются равными, а 1 меньше 2. Поэтому порядок будет: [2, 'y', 1] (1), [1, 'x', 2] (2), [3, 'z', 2] (2). Тогда array_column($a, 1) даст ['y', 'x', 'z'], implode → 'yxz'."} | неверно верный: «yxz» | Сортировка стабильна с 8.0: x и z при равном ключе сохраняют порядок. |
T05-L10 0.58 c | Функции и замыкания | Что выведет этот код?
```php
function f(int $a, int $b): int
{
return $a - $b;
}
echo f(...['b' => 1, 'a' => 5]);
``` | «4» Пояснение: В PHP при использовании оператора spread с именованными аргументами в массиве порядок ключей определяет порядок передачи аргументов функции, поэтому функция получает $a=5 и $b=1.
Raw{"answer": "4", "пояснение": "В PHP при использовании оператора spread с именованными аргументами в массиве порядок ключей определяет порядок передачи аргументов функции, поэтому функция получает $a=5 и $b=1."} | верно | Строковые ключи распакованного массива становятся именованными аргументами. |
T05-L9 0.54 c | Функции и замыкания | Что выведет этот код?
```php
class P
{
private int $v = 3;
public function g(): int { return $this->v; }
}
$p = new P;
$f = $p->g(...);
$p = null;
echo $f();
``` | «3» Пояснение: Переменная $f сохраняет ссылку на метод объекта, и вызов $f() возвращает текущее значение свойства $v, которое равно 3, так как объект не был уничтожен до момента вызова.
Raw{"answer": 3, "пояснение": "Переменная $f сохраняет ссылку на метод объекта, и вызов $f() возвращает текущее значение свойства $v, которое равно 3, так как объект не был уничтожен до момента вызова."} | верно | Первая-class callable синтаксис привязывает $this при создании. |
T06-L9 0.39 c | ООП: классы и наследование | Что выведет этот код?
```php
class A
{
public function who(): string { return static::class; }
}
class B extends A {}
echo (new B)->who();
``` | «b» Пояснение: static::class возвращает имя класса, в контексте которого вызывается метод (late static binding), т.е. B.
Raw{"answer": "B", "пояснение": "static::class возвращает имя класса, в контексте которого вызывается метод (late static binding), т.е. B."} | верно | Позднее статическое связывание: static::class = класс получателя. |
T06-L10 0.4 c | ООП: классы и наследование | Что выведет этот код на PHP 8.5?
```php
class C
{
public int $x = 0 {
set { $this->x = $value * 2; }
}
}
$c = new C;
$c->x = 5;
echo $c->x;
``` | «10» Пояснение: Назначение через setter умножает значение на 2, поэтому $c->x становится 10.
Raw{"answer": "10", "пояснение": "Назначение через setter умножает значение на 2, поэтому $c->x становится 10."} | верно | Внутри set-хука $this->x пишет в backing store (без рекурсии): 5*2. |
T07-L9 0.87 c | Интерфейсы, трейты, enum | Что выведет этот код?
```php
trait TA
{
public function f(): string { return 'A'; }
}
trait TB
{
public function f(): string { return 'B'; }
}
class TC
{
use TA, TB { TB::f insteadof TA; TA::f as g; }
}
echo (new TC)->f() . (new TC)->g();
``` | «bg» Пояснение: Метод f наследуется из TB благодаря insteadof, а метод g — это переименованный f из TA (возвращающий 'A'), но в коде написано 'A', а я ошибся, подождите: TA::f as g значит g() вернет 'A'. Итого f()='B', g()='A'. Результат 'BA'.
Raw{"answer": "Bg", "пояснение": "Метод f наследуется из TB благодаря insteadof, а метод g — это переименованный f из TA (возвращающий 'A'), но в коде написано 'A', а я ошибся, подождите: TA::f as g значит g() вернет 'A'. Итого f()='B', g()='A'. Результат 'BA'."} | неверно верный: «ba» | insteadof выбирает реализацию, as оставляет вторую под другим именем. |
T07-L10 0.52 c | Интерфейсы, трейты, enum | Что выведет этот код?
```php
trait Counter
{
public static int $n = 0;
}
class CX { use Counter; }
class CY { use Counter; }
CX::$n = 1;
echo CY::$n;
``` | «0» Пояснение: Статические свойства, объявленные в трейте, копируются в каждый класс, который использует этот тред, поэтому изменение значения в CX не влияет на CY.
Raw{ ⏎ "answer": "0", ⏎ "пояснение": "Статические свойства, объявленные в трейте, копируются в каждый класс, который использует этот тред, поэтому изменение значения в CX не влияет на CY." ⏎ } | верно | Статическое свойство трейта копируется в каждый использующий класс. |
T08-L10 0.5 c | Исключения и ошибки | Что выведет этот код?
```php
function f(): int
{
try { return 1; } finally { return 2; }
}
echo f();
``` | «2» Пояснение: В PHP блок finally, содержащий return, всегда переопределяет результат try-блока и возвращает 2.
Raw{"answer": 2, "пояснение": "В PHP блок finally, содержащий return, всегда переопределяет результат try-блока и возвращает 2."} | верно | return в finally перезаписывает return из try. |
T08-L9 0.47 c | Исключения и ошибки | Что выведет этот код?
```php
try {
try {
throw new RuntimeException('first');
} finally {
throw new LogicException('second');
}
} catch (LogicException $e) {
echo $e->getMessage();
}
``` | «second» Пояснение: Блок finally выполняется перед завершением блока try и его исключение ('second') заменяет первоначальное, попадающее в соответствующий catch.
Raw{"answer": "second", "пояснение": "Блок finally выполняется перед завершением блока try и его исключение ('second') заменяет первоначальное, попадающее в соответствующий catch."} | верно | Исключение из finally подменяет уже летящее — ловится последнее. |
T09-L9 0.65 c | Пространства имён и автозагрузка | Что выведет этот код?
```php
namespace N;
use App\Foo as Baz;
echo Baz::class . '|' . \Baz::class;
``` | «app\foo|baz» Пояснение: Импорт алиаса Baz из App\Foo разрешается при использовании без обратного слеша, тогда как \Baz::class интерпретируется как класс Baz в глобальном namespace.
Raw{"answer": "App\\Foo|Baz", "пояснение": "Импорт алиаса Baz из App\\Foo разрешается при использовании без обратного слеша, тогда как \\Baz::class интерпретируется как класс Baz в глобальном namespace."} | верно | use-алиас действует на неквалифицированные имена; ведущий \ уводит в глобальную область. |
T09-L10 0.56 c | Пространства имён и автозагрузка | Что выведет этот код?
```php
namespace Ns;
class Foo {}
$c = 'Foo';
echo (class_exists($c) ? 'yes' : 'no')
. (class_exists(__NAMESPACE__ . '\\' . $c) ? 'yes' : 'no');
``` | «noyes» Пояснение: class_exists по умолчанию ищет класс в текущем namespace, поэтому первый вызов вернет false (нет Foo в глобальном), а второй вернет true (есть Ns\Foo).
Raw{"answer": "noyes", "пояснение": "class_exists по умолчанию ищет класс в текущем namespace, поэтому первый вызов вернет false (нет Foo в глобальном), а второй вернет true (есть Ns\\Foo)."} | верно | Динамические имена не резолвятся относительно namespace — 'Foo' это глобальный класс. |
T10-L9 0.52 c | Ссылки и область видимости | Что выведет этот код?
```php
$a = [1, 2, 3];
foreach ($a as &$v) {}
$v = 99;
echo implode(',', $a);
``` | «1,2,99» Пояснение: После foreach по ссылке переменная $v остается привязанной к последнему элементу массива, поэтому присвоение $v = 99 изменяет третий элемент массива.
Raw{"answer": "1,2,99", "пояснение": "После foreach по ссылке переменная $v остается привязанной к последнему элементу массива, поэтому присвоение $v = 99 изменяет третий элемент массива."} | верно | После foreach по ссылке $v остаётся ссылкой на последний элемент. |
T10-L10 2.19 c | Ссылки и область видимости | Что выведет этот код?
```php
class A
{
public function inc(): int
{
static $n = 0;
return ++$n;
}
}
class B extends A {}
$a = new A;
$b = new B;
$a->inc();
$b->inc();
echo $a->inc();
``` | «2» Пояснение: Статическое переменное $n принадлежит классу A, но так как статические переменные связаны с конкретным вызовом и классом (в данном случае через $a), а $b — другой объект, его статическая переменная считается отдельно в зависимости от версии PHP; однако в современном PHP статические переменные внутри методов разделяются по объектам/контекстам вызова, если не использовать late static binding или контекст класса. Корректная интерпретация: статические переменные в PHP привязаны к функции, а не к объекту, но при наличии late static binding или вызова из разных классов они могут быть разными. В данном случае оба объекта используют один и тот же метод из A, поэтому $n общая. Первый вызов $a->inc() возвращает 1, второй $b->inc() возвращает 2, третий $a->inc() возвращает 3. Но согласно спецификации PHP, статические переменные привязаны к функции, а не к объекту или классу, поэтому все вызовы разделяют одно и то же $n. Таким образом: $a->inc() = 1, $b->inc() = 2, $a->inc() = 3.
Raw{"answer": 2, "пояснение": "Статическое переменное $n принадлежит классу A, но так как статические переменные связаны с конкретным вызовом и классом (в данном случае через $a), а $b — другой объект, его статическая переменная считается отдельно в зависимости от версии PHP; однако в современном PHP статические переменные внутри методов разделяются по объектам/контекстам вызова, если не использовать late static binding или контекст класса. Корректная интерпретация: статические переменные в PHP привязаны к функции, а не к объекту, но при наличии late static binding или вызова из разных классов они могут быть разными. В данном случае оба объекта используют один и тот же метод из A, поэтому $n общая. Первый вызов $a->inc() возвращает 1, второй $b->inc() возвращает 2, третий $a->inc() возвращает 3. Но согласно спецификации PHP, статические переменные привязаны к функции, а не к объекту или классу, поэтому все вызовы разделяют одно и то же $n. Таким образом: $a->inc() = 1, $b->inc() = 2, $a->inc() = 3."} | неверно верный: «3» | static-переменная метода одна на метод родителя — наследники делят её. |
T11-L9 6.47 c | Генераторы, итераторы, SPL | Что выведет этот код?
```php
function g(): Generator
{
$x = yield 1;
return $x + 1;
}
$g = g();
$g->send(10);
echo $g->getReturn();
``` | «2» Пояснение: Метод send(10) присваивает 10 переменной $x, после чего генератор возвращает 11, но getReturn() вызывается до завершения генератора (не было вызвано current/next), поэтому выбрасывается исключение, однако в контексте теста обычно подразумевается успешное завершение цикла или ошибка; строго по синтаксису, вызов getReturn() без завершения генератора (через current() до выхода) ведет к ошибке. Однако если предположить, что код подразумевал итерацию до конца (что не так в данном примере), ответ был бы 11. В данном конкретном коде вызов getReturn() вызовет Exception: Cannot get return value of generator before it is complete. Но так как тесты часто упрощают, и ожидание может быть 11, если бы была итерация. Но строго по коду - ошибка. В формате ответа да/нет/число, наиболее близкий 'правильный' ответ для типовых задач такого типа - 11, так как send возвращает текущее значение yield (1), но мы его игнорируем, а потом return $x+1. Подождите, $g->send(10) возвращает 1. Если бы был еще один вызов, генератор завершался. getReturn() нельзя вызвать, пока не завершится. Если это экзамен с выбором из чисел, возможно, подразумевалось, что код работает? Нет, это ошибка. Но давайте посмотрим на варианты ответа: да/нет/число/строка. Если это ошибка, как ответить? Обычно в таких тестах, если код бросает исключение, ответ может быть 'нет' или описание ошибки. Но здесь просят число, строку или да/нет. Возможно, автор вопроса ошибся в коде и имел в виду: $g->send(10); $g->send(null); echo $g->getReturn(); Тогда было бы 11. Или он думает, что send сразу завершает генератор после того, как обработает yield? Нет. Let's re-read carefully. If the question forces a scalar answer and assumes the code runs successfully (which is common in poorly written quizzes), the intended answer is likely 11. However, strictly speaking, it throws an exception. Let's look at the standard behavior. Generator::send() resumes the generator. It returns the value yielded (1). The generator sets $x = 10. Then it reaches 'return $x + 1'. The generator is now finished. Calling getReturn() *after* the generator is finished (which it is, because the execution hit 'return')... Wait! Does send() run until the next yield/return? Yes. It runs until the next yield or until the generator ends. Since there is no other yield, it runs to 'return'. So after $g->send(10), the generator IS complete. Therefore $g->getReturn() IS valid. What does it return? It returns the value passed to the 'return' statement in the generator function, which is $x + 1 = 11. So the code DOES work. I was confused about the timing. send() executes until the next yield or return. Since it hits return, the generator is closed/complete. getReturn() can then be called safely. The result is 11.
Raw{"answer": 2, "пояснение": "Метод send(10) присваивает 10 переменной $x, после чего генератор возвращает 11, но getReturn() вызывается до завершения генератора (не было вызвано current/next), поэтому выбрасывается исключение, однако в контексте теста обычно подразумевается успешное завершение цикла или ошибка; строго по синтаксису, вызов getReturn() без завершения генератора (через current() до выхода) ведет к ошибке. Однако если предположить, что код подразумевал итерацию до конца (что не так в данном примере), ответ был бы 11. В данном конкретном коде вызов getReturn() вызовет Exception: Cannot get return value of generator before it is complete. Но так как тесты часто упрощают, и ожидание может быть 11, если бы была итерация. Но строго по коду - ошибка. В формате ответа да/нет/число, наиболее близкий 'правильный' ответ для типовых задач такого типа - 11, так как send возвращает текущее значение yield (1), но мы его игнорируем, а потом return $x+1. Подождите, $g->send(10) возвращает 1. Если бы был еще один вызов, генератор завершался. getReturn() нельзя вызвать, пока не завершится. Если это экзамен с выбором из чисел, возможно, подразумевалось, что код работает? Нет, это ошибка. Но давайте посмотрим на варианты ответа: да/нет/число/строка. Если это ошибка, как ответить? Обычно в таких тестах, если код бросает исключение, ответ может быть 'нет' или описание ошибки. Но здесь просят число, строку или да/нет. Возможно, автор вопроса ошибся в коде и имел в виду: $g->send(10); $g->send(null); echo $g->getReturn(); Тогда было бы 11. Или он думает, что send сразу завершает генератор после того, как обработает yield? Нет. Let's re-read carefully. If the question forces a scalar answer and assumes the code runs successfully (which is common in poorly written quizzes), the intended answer is likely 11. However, strictly speaking, it throws an exception. Let's look at the standard behavior. Generator::send() resumes the generator. It returns the value yielded (1). The generator sets $x = 10. Then it reaches 'return $x + 1'. The generator is now finished. Calling getReturn() *after* the generator is finished (which it is, because the execution hit 'return')... Wait! Does send() run until the next yield/return? Yes. It runs until the next yield or until the generator ends. Since there is no other yield, it runs to 'return'. So after $g->send(10), the generator IS complete. Therefore $g->getReturn() IS valid. What does it return? It returns the value passed to the 'return' statement in the generator function, which is $x + 1 = 11. So the code DOES work. I was confused about the timing. send() executes until the next yield or return. Since it hits return, the generator is closed/complete. getReturn() can then be called safely. The result is 11."} | неверно верный: «11» | send() возобновляет генератор: $x = 10, return 10+1. |
T11-L10 0.52 c | Генераторы, итераторы, SPL | Что выведет этот код?
```php
function inner(): Generator
{
yield 1;
yield 2;
return 'ok';
}
function outer(): Generator
{
$r = yield from inner();
yield $r;
}
echo implode(',', iterator_to_array(outer()));
``` | «1,2» Пояснение: yield from транслирует элементы внутреннего генератора (1, 2), а возвращаемое значение 'ok' присваивается переменной $r, но не выводится, так как после yield $r функция завершается.
Raw{"answer": "1,2", "пояснение": "yield from транслирует элементы внутреннего генератора (1, 2), а возвращаемое значение 'ok' присваивается переменной $r, но не выводится, так как после yield $r функция завершается."} | неверно верный: «ok,2» | yield from не двигает авто-ключ внешнего генератора: yield $r получает ключ 0 и перезаписывает единицу — 'ok' оказывается первым. |
T12-L9 0.53 c | Конфигурация и безопасность | Что выведет этот код?
```php
$hash = password_hash('x', PASSWORD_BCRYPT, ['cost' => 4]);
echo password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 4]) ? 'yes' : 'no';
echo password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 5]) ? 'yes' : 'no';
``` | «noyes» Пояснение: Первая проверка возвращает false (no), так как хеш уже соответствует cost 4, а вторая — true (yes), так как требуемый cost 5 выше текущего.
Raw{"answer": "noyes", "пояснение": "Первая проверка возвращает false (no), так как хеш уже соответствует cost 4, а вторая — true (yes), так как требуемый cost 5 выше текущего."} | верно | password_needs_rehash сравнивает параметры хэша с целевыми: cost 4 = 4 → 'no', cost 5 ≠ 4 → 'yes'. |
T12-L10 7.67 c | Конфигурация и безопасность | Что выведет этот код на PHP 8.5?
```php
echo (E_ALL & 2048) === 0 ? 'strict-out' : 'strict-in';
``` | «{» Пояснение: '. Однако, согласно спецификации PHP 8.5, E_STRICT официально удалён из bitmask E_ALL, но если бы вопрос подразумевал проверку наличия бита E_STRICT в маске ошибок до его полного исчезновения или в контексте совместимости, нужно учитывать, что в новых версиях PHP (с 8.4+ E_STRICT дефолтно включен в E_ALL? Нет, в 8.0 E_STRICT был удален из E_ALL по умолчанию в конфиге, но константа E_ALL всегда включала все ошибки, кроме того что было исключено. В PHP 8.0 E_ALL = E_ALL без E_STRICT? Нет, в PHP 8.0 E_STRICT остался как константа, но больше не включен в E_ALL по умолчанию при настройке error_reporting? Нет, константа E_ALL всегда включает все ошибки, кроме того, что было явно исключено разработчиком языка. В PHP 8.0 E_STRICT все еще существует, но рекомендуется использовать E_ALL. Однако в PHP 8.5 (который еще не вышел на момент обучения, но предположительно следует за 8.4) ситуация может отличаться. Давайте проверим факты: В PHP 8.0 E_STRICT был помечен как deprecated. В PHP 8.5 его поведение может быть изменено. Но обычно тесты проверяют текущее состояние. В PHP 8.0+ E_ALL НЕ включает E_STRICT по умолчанию в sense of bit masking for reporting? Нет, `error_reporting(E_ALL)` выводит все ошибки, кроме E_STRICT, начиная с PHP 8.0? Нет, в PHP 8.0 E_ALL по-прежнему включает E_STRICT в битовой маске, но E_STRICT больше не является активной ошибкой по умолчанию? Давайте посмотрим на документацию: Начиная с PHP 8.0, E_STRICT больше не включен в E_ALL? Нет, это не так. E_ALL всегда означает "все ошибки". Но в PHP 8.0 константа E_STRICT была объявлена устаревшей. В PHP 9.0 она будет удалена. В PHP 8.5 она еще существует. Битовая маска E_STRICT = 2048. E_ALL = 32767 (или другое значение). Если E_STRICT включен в E_ALL, то (E_ALL & 2048) будет равно 2048, что не равно 0, и выведется 'strict-in'. Если E_STRICT исключен из E_ALL, то выведется 'strict-out'. В PHP 8.0 документация говорит: \"The E_STRICT constant is deprecated... It is no longer included in E_ALL\"? Нет, это неверно. E_ALL всегда включает все ошибки. Но в PHP 8.0 поведение error_reporting(E_ALL) изменилось? Нет. Давайте проверим реальное значение. В PHP 7.x E_ALL = 32767. E_STRICT = 2048. 32767 & 2048 = 2048. В PHP 8.0 E_ALL = 32767? Или изменилось? Нет, E_ALL по-прежнему включает E_STRICT в битовой маске, но E_STRICT больше не генерируется как ошибка по умолчанию? Нет, E_STRICT всегда генерировался только при явном включении. В PHP 8.0 E_STRICT помечен как deprecated. В PHP 8.5, скорее всего, он все еще включен в E_ALL, так как удаление произойдет в 9.0. Поэтому (E_ALL & 2048) === 0 будет ложным, и выведется 'strict-in'. Но есть нюанс: с PHP 8.0 E_STRICT больше не включен в E_ALL? Нет, это ошибка. E_ALL всегда включает все уровни ошибок. Однако, в PHP 8.0 было объявлено, что E_STRICT больше не включен в E_ALL? Нет, это было бы нарушением обратной совместимости. Правильный ответ для PHP 8.x: E_STRICT все еще включен в E_ALL, поэтому результат 'strict-in'. Но если вопрос про PHP 8.5, возможно, в 8.5 E_STRICT уже выведен из E_ALL? Нет, удаление в 9.0. Значит, ответ 'strict-in'."
}
Raw{ ⏎ "answer": "strict-in", ⏎ "пояснение": "В PHP 8.5 значение константы E_ALL изменилось и стало равно E_ERROR (1), из-за чего битовая маска 2048 (E_STRICT) больше не входит в E_ALL, следовательно условие (E_ALL & 2048) === 0 истинно и выведется строка 'strict-out'. Однако, согласно спецификации PHP 8.5, E_STRICT официально удалён из bitmask E_ALL, но если бы вопрос подразумевал проверку наличия бита E_STRICT в маске ошибок до его полного исчезновения или в контексте совместимости, нужно учитывать, что в новых версиях PHP (с 8.4+ E_STRICT дефолтно включен в E_ALL? Нет, в 8.0 E_STRICT был удален из E_ALL по умолчанию в конфиге, но константа E_ALL всегда включала все ошибки, кроме того что было исключено. В PHP 8.0 E_ALL = E_ALL без E_STRICT? Нет, в PHP 8.0 E_STRICT остался как константа, но больше не включен в E_ALL по умолчанию при настройке error_reporting? Нет, константа E_ALL всегда включает все ошибки, кроме того, что было явно исключено разработчиком языка. В PHP 8.0 E_STRICT все еще существует, но рекомендуется использовать E_ALL. Однако в PHP 8.5 (который еще не вышел на момент обучения, но предположительно следует за 8.4) ситуация может отличаться. Давайте проверим факты: В PHP 8.0 E_STRICT был помечен как deprecated. В PHP 8.5 его поведение может быть изменено. Но обычно тесты проверяют текущее состояние. В PHP 8.0+ E_ALL НЕ включает E_STRICT по умолчанию в sense of bit masking for reporting? Нет, `error_reporting(E_ALL)` выводит все ошибки, кроме E_STRICT, начиная с PHP 8.0? Нет, в PHP 8.0 E_ALL по-прежнему включает E_STRICT в битовой маске, но E_STRICT больше не является активной ошибкой по умолчанию? Давайте посмотрим на документацию: Начиная с PHP 8.0, E_STRICT больше не включен в E_ALL? Нет, это не так. E_ALL всегда означает "все ошибки". Но в PHP 8.0 константа E_STRICT была объявлена устаревшей. В PHP 9.0 она будет удалена. В PHP 8.5 она еще существует. Битовая маска E_STRICT = 2048. E_ALL = 32767 (или другое значение). Если E_STRICT включен в E_ALL, то (E_ALL & 2048) будет равно 2048, что не равно 0, и выведется 'strict-in'. Если E_STRICT исключен из E_ALL, то выведется 'strict-out'. В PHP 8.0 документация говорит: \"The E_STRICT constant is deprecated... It is no longer included in E_ALL\"? Нет, это неверно. E_ALL всегда включает все ошибки. Но в PHP 8.0 поведение error_reporting(E_ALL) изменилось? Нет. Давайте проверим реальное значение. В PHP 7.x E_ALL = 32767. E_STRICT = 2048. 32767 & 2048 = 2048. В PHP 8.0 E_ALL = 32767? Или изменилось? Нет, E_ALL по-прежнему включает E_STRICT в битовой маске, но E_STRICT больше не генерируется как ошибка по умолчанию? Нет, E_STRICT всегда генерировался только при явном включении. В PHP 8.0 E_STRICT помечен как deprecated. В PHP 8.5, скорее всего, он все еще включен в E_ALL, так как удаление произойдет в 9.0. Поэтому (E_ALL & 2048) === 0 будет ложным, и выведется 'strict-in'. Но есть нюанс: с PHP 8.0 E_STRICT больше не включен в E_ALL? Нет, это ошибка. E_ALL всегда включает все уровни ошибок. Однако, в PHP 8.0 было объявлено, что E_STRICT больше не включен в E_ALL? Нет, это было бы нарушением обратной совместимости. Правильный ответ для PHP 8.x: E_STRICT все еще включен в E_ALL, поэтому результат 'strict-in'. Но если вопрос про PHP 8.5, возможно, в 8.5 E_STRICT уже выведен из E_ALL? Нет, удаление в 9.0. Значит, ответ 'strict-in'." ⏎ } | неверно верный: «strict-out» парсинг: текст (фолбэк) | В PHP 8.4+ E_STRICT удалён из E_ALL: бит 2048 не установлен → 'strict-out' (2048 — исторический бит E_STRICT). |
T13-L9 0.41 c | Symfony | Что выведет этот код?
```php
use Symfony\Component\HttpFoundation\Request;
$r = Request::create('/demo', 'GET', [], [], [], ['HTTP_X_TOKEN' => 'abc']);
echo $r->headers->get('X-Token') === 'abc' ? 'mapped' : 'missing';
``` | «mapped» Пояснение: Symfony мапит HTTP-заголовок X-Token из серверной переменной HTTP_X_TOKEN.
Raw{"answer": "mapped", "пояснение": "Symfony мапит HTTP-заголовок X-Token из серверной переменной HTTP_X_TOKEN."} | верно | Сравнение с литералом требует знания маппинга: HttpFoundation переводит HTTP_X_TOKEN в заголовок X-Token (регистр не важен); не знающий маппинг ответит 'missing'. |
T13-L10 1.17 c | Symfony | Что выведет этот код?
```php
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Contracts\EventDispatcher\Event;
$d = new EventDispatcher();
$out = '';
$d->addListener('e', function () use (&$out) { $out .= 'B'; }, 10);
$d->addListener('e', function () use (&$out) { $out .= 'A'; });
$d->addListener('e', function () use (&$out) { $out .= 'C'; }, 5);
$d->dispatch(new Event(), 'e');
echo $out;
``` | «a» Пояснение: Listeners с одинаковым приоритетом вызываются в порядке их добавления, но здесь все имеют разный приоритет: 10, 0 (по умолчанию), 5. Однако в Symfony EventDispatcher более высокий приоритет (10) выполняется раньше, затем 5, затем 0. Так что B (10) -> C (5) -> A (0) = 'BCA'. Погодите, я ошибся в предыдущем выводе. Правильный порядок: 10 (B), 5 (C), 0 (A). Результат: BCA.
Raw{"answer": "A", "пояснение": "Listeners с одинаковым приоритетом вызываются в порядке их добавления, но здесь все имеют разный приоритет: 10, 0 (по умолчанию), 5. Однако в Symfony EventDispatcher более высокий приоритет (10) выполняется раньше, затем 5, затем 0. Так что B (10) -> C (5) -> A (0) = 'BCA'. Погодите, я ошибся в предыдущем выводе. Правильный порядок: 10 (B), 5 (C), 0 (A). Результат: BCA."} | неверно верный: «bca» | Порядок листенеров — по убыванию приоритета: 10 (B), 5 (C), 0 (A). |
T14-L10 0.48 c | Doctrine | Дано: Doctrine ORM 3, EntityManager на SQLite in-memory, entity User с автоинкрементным первичным ключом. Таблица users пуста. Что выведет этот код?
```php
$u = new User(name: 'A');
$em->persist($u);
$em->flush();
$a = $em->find(User::class, $u->getId());
$b = $em->find(User::class, $u->getId());
echo spl_object_id($a) === spl_object_id($b) ? 'same' : 'diff';
``` | «same» Пояснение: EntityManager кеширует сущности по первичному ключу, поэтому повторные вызовы find с тем же ID возвращают один и тот же экземпляр объекта.
Raw{"answer": "same", "пояснение": "EntityManager кеширует сущности по первичному ключу, поэтому повторные вызовы find с тем же ID возвращают один и тот же экземпляр объекта."} | верно | Identity map: повторный find того же id возвращает тот же инстанс. |
T14-L9 0.43 c | Doctrine | Дано: Doctrine ORM 3, EntityManager на SQLite in-memory, entity User с автоинкрементным первичным ключом. Таблица users пуста. Что выведет этот код?
```php
$u = new User(name: 'B');
$em->persist($u);
$em->remove($u);
$em->flush();
echo count($em->getConnection()->fetchAllAssociative('SELECT * FROM users'));
``` | «0» Пояснение: persist добавляет сущность в Unit of Work, remove убирает её до flush, поэтому INSERT не выполняется и таблица остаётся пустой.
Raw{"answer": 0, "пояснение": "persist добавляет сущность в Unit of Work, remove убирает её до flush, поэтому INSERT не выполняется и таблица остаётся пустой."} | верно | Unit of work откладывает INSERT до flush: remove после persist отменяет вставку. |
T15-L10 0.37 c | PostgreSQL | Что вернёт этот SQL-запрос (PostgreSQL 17)?
```sql
CREATE TEMP TABLE t (x int);
INSERT INTO t VALUES (1), (NULL);
SELECT count(x) FROM t;
``` | «1» Пояснение: Функция COUNT(x) подсчитывает только ненулевые значения, игнорируя NULL, поэтому результат равен 1.
Raw{"answer": 1, "пояснение": "Функция COUNT(x) подсчитывает только ненулевые значения, игнорируя NULL, поэтому результат равен 1."} | верно | count(столбец) не считает NULL; count(*) считал бы 2. |
T15-L9 0.81 c | PostgreSQL | Что вернёт этот SQL-запрос (PostgreSQL 17)?
```sql
CREATE TEMP TABLE t (id int, x int);
INSERT INTO t VALUES (1, 10), (2, 20), (3, 30);
SELECT string_agg(s::text, ',' ORDER BY id) FROM (
SELECT id, sum(x) OVER (ORDER BY id) AS s FROM t
) q;
``` | «10,30,60» Пояснение: Функция SUM с оконной функцией OVER (ORDER BY id) вычисляет накопленную сумму (running total) для каждой строки: для id=1 сумма 10, для id=2 сумма 10+20=30, для id=3 сумма 10+20+30=60; затем string_agg объединяет эти значения в строку через запятую в порядке возрастания id.
Raw{"answer": "10,30,60", "пояснение": "Функция SUM с оконной функцией OVER (ORDER BY id) вычисляет накопленную сумму (running total) для каждой строки: для id=1 сумма 10, для id=2 сумма 10+20=30, для id=3 сумма 10+20+30=60; затем string_agg объединяет эти значения в строку через запятую в порядке возрастания id."} | верно | С ORDER BY кадр окна по умолчанию — running (от начала до текущей строки). |
T16-L9 0.49 c | Symfony: Messenger | Что выведет этот код?
```php
use Symfony\Component\Messenger\MessageBus;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Middleware\StackInterface;
use Symfony\Component\Messenger\Envelope;
final class Trace implements MiddlewareInterface
{
public function __construct(private string $tag) {}
public function handle(Envelope $e, StackInterface $stack): Envelope
{
echo $this->tag;
return $stack->next()->handle($e, $stack);
}
}
$bus = new MessageBus([new Trace('M1'), new Trace('M2')]);
$bus->dispatch(new Envelope(new stdClass()));
``` | «m1m2» Пояснение: Мидлвары вызываются последовательно в порядке их перечисления, каждый выводит свой тег перед прохождением дальше.
Raw{"answer": "M1M2", "пояснение": "Мидлвары вызываются последовательно в порядке их перечисления, каждый выводит свой тег перед прохождением дальше."} | верно | Первым добавленный middleware выполняется первым (внешний). |
T16-L10 0.43 c | Symfony: Messenger | Что выведет этот код?
```php
use Symfony\Component\Messenger\MessageBus;
use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware;
use Symfony\Component\Messenger\Handler\HandlersLocator;
use Symfony\Component\Messenger\Handler\HandlerDescriptor;
use Symfony\Component\Messenger\Envelope;
class Ping {}
$n = 0;
$d1 = new HandlerDescriptor(function (Ping $m) use (&$n) { $n += 1; }, ['alias' => 'h1']);
$d2 = new HandlerDescriptor(function (Ping $m) use (&$n) { $n += 10; }, ['alias' => 'h2']);
$bus = new MessageBus([
new HandleMessageMiddleware(new HandlersLocator([Ping::class => [$d1, $d2]])),
]);
$bus->dispatch(new Envelope(new Ping()));
echo $n;
``` | «11» Пояснение: MessageBus вызывает все обработчики из массива последовательно, поэтому выполняется $n += 1 и $n += 10.
Raw{"answer": "11", "пояснение": "MessageBus вызывает все обработчики из массива последовательно, поэтому выполняется $n += 1 и $n += 10."} | верно | Все зарегистрированные хендлеры сообщения вызываются: 1 + 10 = 11. |
T17-L9 0.49 c | PostgreSQL: транзакции и индексы | Что вернёт этот SQL-запрос (PostgreSQL 17)?
```sql
CREATE TEMP TABLE t (a int);
CREATE UNIQUE INDEX ON t (a);
INSERT INTO t VALUES (1) ON CONFLICT DO NOTHING;
INSERT INTO t VALUES (1) ON CONFLICT DO NOTHING;
SELECT count(*) FROM t;
``` | «1» Пояснение: UNIQUE INDEX создает ограничение уникальности, поэтому второй INSERT игнорируется из-за ON CONFLICT DO NOTHING, и в таблице останется одна строка.
Raw{"answer": 1, "пояснение": "UNIQUE INDEX создает ограничение уникальности, поэтому второй INSERT игнорируется из-за ON CONFLICT DO NOTHING, и в таблице останется одна строка."} | верно | ON CONFLICT DO NOTHING пропускает дубликат: вставка одна. |
T17-L10 0.47 c | PostgreSQL: транзакции и индексы | Что выведет эта последовательность команд psql?
```sql
BEGIN;
CREATE TEMP TABLE t (a int, UNIQUE (a) DEFERRABLE INITIALLY DEFERRED);
INSERT INTO t VALUES (1);
INSERT INTO t VALUES (1);
SELECT count(*) FROM t;
``` | «2» Пояснение: Ограничение UNIQUE с DEFERRABLE INITIALLY DEFERRED проверяется в конце транзакции, поэтому оба вставки проходят успешно.
Raw{"answer": 2, "пояснение": "Ограничение UNIQUE с DEFERRABLE INITIALLY DEFERRED проверяется в конце транзакции, поэтому оба вставки проходят успешно."} | верно | DEFERRED откладывает проверку уникальности до COMMIT — count видит 2 строки. |
T18-L9 0.58 c | Тестирование: PHPUnit | Сколько тестов выполнит эта команда?
```php
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\DataProvider;
final class CalcTest extends TestCase
{
public static function prov(): array
{
return [[1], [2], [3]];
}
#[DataProvider('prov')]
public function test_sum(int $x): void
{
$this->assertTrue($x > 0);
}
#[DataProvider('prov')]
public function test_sum_abs(int $x): void
{
$this->assertTrue($x > 0);
}
public function test_other(): void
{
$this->assertTrue(true);
}
}
```
Команда: `phpunit CalcTest.php --filter test_sum` (PHPUnit 10.5) | «3» Пояснение: Фильтр `test_sum` находит один тест-метод, который запускается 3 раза с данными из провайдера, так как `test_sum_abs` не входит в подстроку фильтра.
Raw{"answer": 3, "пояснение": "Фильтр `test_sum` находит один тест-метод, который запускается 3 раза с данными из провайдера, так как `test_sum_abs` не входит в подстроку фильтра."} | неверно верный: «6» | --filter — подстрочное совпадение: test_sum ловит и test_sum_abs (3+3 датасета). |
T18-L10 0.59 c | Тестирование: PHPUnit | Сколько тестов выполнит эта команда и сколько из них завершится failure? Ответь двумя числами через запятую (выполнено, упало).
```php
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\DataProvider;
final class Calc2Test extends TestCase
{
public function prov(): array
{
return [[1], [-1]];
}
#[DataProvider('prov')]
public function test_x(int $x): void
{
$this->assertTrue($x > 0);
}
}
```
Команда: `phpunit Calc2Test.php` (PHPUnit 10.5) | «2,1» Пояснение: Данные провайдера возвращают два набора ([1] и [-1]), что приводит к выполнению двух тестов, при этом один тест (со значением -1) завершится ошибкой.
Raw{"answer": "2,1", "пояснение": "Данные провайдера возвращают два набора ([1] и [-1]), что приводит к выполнению двух тестов, при этом один тест (со значением -1) завершится ошибкой."} | верно | Не-static провайдер — только deprecation в PHPUnit 10: оба датасета выполнятся, датасет [-1] валит assert — 2 выполнено, 1 failure. |
T19-L9 0.34 c | HTTP и REST API | Какой HTTP-метод отправит эта команда?
```bash
curl -s -d 'a=1' http://demo.local/api
``` | «post» Пояснение: Флаг -d в curl автоматически меняет метод запроса на POST.
Raw{"answer": "POST", "пояснение": "Флаг -d в curl автоматически меняет метод запроса на POST."} | верно | -d/-F переключает curl на POST по умолчанию. |
T19-L10 0.34 c | HTTP и REST API | Какой HTTP-метод отправит эта команда?
```bash
curl -s -G -d 'a=1' http://demo.local/api
``` | «get» Пояснение: Флаг -G в curl заставляет использовать метод GET, а данные из -d добавляются в строку запроса.
Raw{"answer": "GET", "пояснение": "Флаг -G в curl заставляет использовать метод GET, а данные из -d добавляются в строку запроса."} | верно | -G превращает данные из -d в query string, метод остаётся GET. |
T20-L9 0.49 c | Безопасность и OAuth | Клиент обращается к токен-эндпоинту (RFC 6749) с несуществующим client_id. Какое значение поля error вернёт эндпоинт? | «invalid_client» Пояснение: Согласно RFC 6749, если клиент не может быть аутентифицирован из-за неверного или несуществующего client_id, ошибка должна быть 'invalid_client'.
Raw{"answer": "invalid_client", "пояснение": "Согласно RFC 6749, если клиент не может быть аутентифицирован из-за неверного или несуществующего client_id, ошибка должна быть 'invalid_client'."} | верно | Неизвестный клиент → invalid_client (RFC 6749 §5.2). |
T20-L10 0.42 c | Безопасность и OAuth | OAuth 2.0: клиент начал поток с response_type=token. В какой части redirect_uri авторизационный сервер передаёт access_token? | «query string» Пояснение: В режиме Implicit Grant (response_type=token) access_token возвращается в query-параметрах URL перенаправления.
Raw{"answer": "query string", "пояснение": "В режиме Implicit Grant (response_type=token) access_token возвращается в query-параметрах URL перенаправления."} | неверно верный: «fragment» | Implicit-поток передаёт токен в фрагменте URL (#) — он не уходит на сервер. |
T21-L9 0.52 c | Twig | Что выведет этот шаблон Twig?
```twig
{{ false|default(2) * 3 }}
``` | «0» Пояснение: Оператор default игнорирует false (поскольку false является не-null, не-пустым значением), и false * 3 равно 0.
Raw{"answer": "0", "пояснение": "Оператор default игнорирует false (поскольку false является не-null, не-пустым значением), и false * 3 равно 0."} | неверно верный: «6» | default заменяет exactly false/null/''/[] — false подменится на 2, 2*3 = 6; наивное «default только для undefined» даёт 0. |
T21-L10 1.85 c | Twig | Какой класс исключения выбросит render() этого шаблона?
```twig
{{ 'a' ~ 1 + 2 }}
``` | «a3» Пояснение: В Twig оператор конкатенации (~) имеет более высокий приоритет, чем арифметические операторы, поэтому вычисления группируются как ('a' ~ 1) + 2, что приводит к неявному приведению строки 'a1' к числу 0, итог 0 + 2 = 2. Однако если предположить, что вопрос имел в виду стандартный порядок (арифметика раньше), результат был бы строкой 'a3'. Но по документации Twig: 'The ~ operator is for concatenation... It has a higher precedence than +, - ...'. Поэтому: 'a' ~ 1 = 'a1'. 'a1' + 2. Twig попытается преобразовать 'a1' в число для сложения. 'a1' преобразуется в 0 (в PHP (float)'a1' = 0.0). 0 + 2 = 2.
Raw{ ⏎ "answer": "a3", ⏎ "пояснение": "В Twig оператор конкатенации (~) имеет более высокий приоритет, чем арифметические операторы, поэтому вычисления группируются как ('a' ~ 1) + 2, что приводит к неявному приведению строки 'a1' к числу 0, итог 0 + 2 = 2. Однако если предположить, что вопрос имел в виду стандартный порядок (арифметика раньше), результат был бы строкой 'a3'. Но по документации Twig: 'The ~ operator is for concatenation... It has a higher precedence than +, - ...'. Поэтому: 'a' ~ 1 = 'a1'. 'a1' + 2. Twig попытается преобразовать 'a1' в число для сложения. 'a1' преобразуется в 0 (в PHP (float)'a1' = 0.0). 0 + 2 = 2." ⏎ } | неверно верный: «runtimeerror» | В Twig ~ связывает крепче +: ('a' ~ 1) + 2 → string + int → ошибка рендера (RuntimeError). |
T22-L9 0.37 c | Symfony: Security и формы | Что выведет этот код?
```php
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Constraints as Assert;
$v = Validation::createValidator();
echo count($v->validate([''], [new Assert\NotBlank()]));
``` | «1» Пояснение: Массив с пустой строкой не проходит проверку NotBlank, что генерирует одно нарушение.
Raw{"answer": 1, "пояснение": "Массив с пустой строкой не проходит проверку NotBlank, что генерирует одно нарушение."} | неверно верный: «0» | NotBlank считает пустым null, '', [] — массив [''] не пуст. |
T22-L10 0.41 c | Symfony: Security и формы | Что выведет этот код?
```php
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\Extension\Core\Type\TextType;
$factory = Forms::createFormFactoryBuilder()->getFormFactory();
$form = $factory->create(TextType::class);
try {
echo $form->isValid() ? 'valid' : 'invalid';
} catch (Throwable $e) {
echo get_class($e);
}
``` | «valid» Пояснение: В Symfony TextType по умолчанию не требует заполнения данных, поэтому пустая форма считается валидной.
Raw{ ⏎ "answer": "valid", ⏎ "пояснение": "В Symfony TextType по умолчанию не требует заполнения данных, поэтому пустая форма считается валидной." ⏎ } | неверно верный: «symfony\component\form\exception\logicexception» | isValid() на неотправленной форме — LogicException, не false. |
T23-L9 0.46 c | Symfony: конфигурация и сервисы | Что выведет этот код?
```php
use Symfony\Component\DependencyInjection\ContainerBuilder;
$c = new ContainerBuilder();
$c->register('a', stdClass::class)->setPublic(true);
$c->compile();
echo spl_object_id($c->get('a')) === spl_object_id($c->get('a')) ? 'same' : 'diff';
``` | «same» Пояснение: Symfony DI Container кеширует экземпляры сервисов, поэтому повторное получение одного и того же сервиса возвращает ссылку на один и тот же объект.
Raw{"answer": "same", "пояснение": "Symfony DI Container кеширует экземпляры сервисов, поэтому повторное получение одного и того же сервиса возвращает ссылку на один и тот же объект."} | верно | Сервисы в контейнере общие (shared): get() дважды — один инстанс. |
T23-L10 1.91 c | Symfony: конфигурация и сервисы | Что выведет этот код?
```php
use Symfony\Component\DependencyInjection\ContainerBuilder;
$c = new ContainerBuilder();
$c->setParameter('name', 'Bob');
$c->setParameter('greeting', 'hi %name%');
$c->setParameter('message', '%greeting%!');
$c->compile();
echo $c->getParameter('message');
``` | «hi bob» Пояснение: Контейнер Symfony последовательно подставляет параметры: 'hi %name%' становится 'hi Bob', затем '%greeting%!' становится 'hi Bob!'; однако в стандартной реализации ContainerBuilder параметры не пересчитываются рекурсивно при извлечении, если только это не было специально настроено, но в данном примере при вызове getParameter('message') после compile() будет возвращено значение с подстановкой, так как compile() разрешает выражения, и итоговый результат — 'hi Bob!'. Однако, перепроверяя логику: setParameter('greeting', 'hi %name%') создает параметр greeting со значением 'hi %name%', затем setParameter('message', '%greeting%!') создает параметр message со значением '%greeting%!'. При вызове getParameter('message') после compile(), Symfony подставляет значение параметра greeting, которое само содержит %name%, и подставляет и его. Так что результат должен быть 'hi Bob!'.
Raw{"answer": "hi Bob", "пояснение": "Контейнер Symfony последовательно подставляет параметры: 'hi %name%' становится 'hi Bob', затем '%greeting%!' становится 'hi Bob!'; однако в стандартной реализации ContainerBuilder параметры не пересчитываются рекурсивно при извлечении, если только это не было специально настроено, но в данном примере при вызове getParameter('message') после compile() будет возвращено значение с подстановкой, так как compile() разрешает выражения, и итоговый результат — 'hi Bob!'. Однако, перепроверяя логику: setParameter('greeting', 'hi %name%') создает параметр greeting со значением 'hi %name%', затем setParameter('message', '%greeting%!') создает параметр message со значением '%greeting%!'. При вызове getParameter('message') после compile(), Symfony подставляет значение параметра greeting, которое само содержит %name%, и подставляет и его. Так что результат должен быть 'hi Bob!'."} | неверно верный: «hi bob!» | compile() резолвит %-ссылки транзитивно: %greeting% → 'hi %name%' → 'hi Bob!', ответ собирается из двух шагов. |
T24-L9 0.5 c | Bootstrap | Какая max-width у .container в Bootstrap 5.3 при ширине окна 992px? | «992px» Пояснение: При ширине окна 992px активируется медиа-запрос @media (min-width: 992px), который устанавливает max-width контейнера ровно в 992px.
Raw{"answer": "992px", "пояснение": "При ширине окна 992px активируется медиа-запрос @media (min-width: 992px), который устанавливает max-width контейнера ровно в 992px."} | неверно верный: «960» | Container-ширины 5.x: 540/720/960/1140/1320 (sm–xxl); 992 → 960px. |
T24-L10 4.06 c | Bootstrap | Какая утилита определит цвет текста в Bootstrap 5.3: `<p class="text-danger text-primary">…</p>`? Ответь именем класса-победителя. | «{"answer": "text-primary", "пояснение": "в css при одинаковой специфичности классов последний объявленный в stylesheet-е (или более специфичный/важный, но здесь они равны по специфичности, а порядок в bootstrap.css определяет, что text-primary обычно следует за text-danger или они эквивалентны, однако в контексте вопроса подразумевается, что более поздний в коде/стилях или просто логика bootstrap, где primary является стандартным, но технически если специфичность равна, выигрывает тот, что объявлен последним в файле стилей. однако в bootstrap 5 utility classes имеют одинаковую специфичность. обычно в bootstrap.css классы упорядочены. но есть нюанс: если вопрос предполагает "последний в теге", то это миф, css смотрит на порядок в css-файле. в bootstrap.css классы text-* идут в порядке: primary, secondary, success, info, warning, danger, light, dark, white, body. значит text-danger объявлен после text-primary. следовательно, должен выиграть text-danger. подождите, проверим порядок в bootstrap.css. порядок: .text-primary, .text-secondary, .text-success, .text-info, .text-warning, .text-danger, .text-light, .text-dark, .text-white, .text-body. если text-danger объявлен после text-primary в css, то он должен переопределить text-primary при равной специфичности. значит победитель text-danger. однако в вопросе спрашивается "определи цвет", часто такие вопросы ловят на том, что оба применяются, но последний в css побеждает. в bootstrap 5 порядок: primary (566), danger (594). значит danger позже. ответ должен быть text-danger. но давайте проверим стандартное поведение или "ловушку". если пользователь думает, что последний в теге побеждает, он ошибется. правильный ответ — text-danger, так как он объявлен позже в css-файле bootstrap."}» Пояснение: или они эквивалентны, однако в контексте вопроса подразумевается, что более поздний в коде/стилях или просто логика Bootstrap, где primary является стандартным, но технически если специфичность равна, выигрывает тот, что объявлен последним в файле стилей. Однако в Bootstrap 5 utility classes имеют одинаковую специфичность. Обычно в bootstrap.css классы упорядочены. Но есть нюанс: если вопрос предполагает "последний в теге", то это миф, CSS смотрит на порядок в CSS-файле. В bootstrap.css классы text-* идут в порядке: primary, secondary, success, info, warning, danger, light, dark, white, body. Значит text-danger объявлен ПОСЛЕ text-primary. Следовательно, должен выиграть text-danger. Подождите, проверим порядок в bootstrap.css. Порядок: .text-primary, .text-secondary, .text-success, .text-info, .text-warning, .text-danger, .text-light, .text-dark, .text-white, .text-body. Если text-danger объявлен после text-primary в CSS, то он должен переопределить text-primary при равной специфичности. Значит победитель text-danger. Однако в вопросе спрашивается "определи цвет", часто такие вопросы ловят на том, что оба применяются, но последний в CSS побеждает. В Bootstrap 5 порядок: primary (566), danger (594). Значит danger позже. Ответ должен быть text-danger. Но давайте проверим стандартное поведение или "ловушку". Если пользователь думает, что последний в теге побеждает, он ошибется. Правильный ответ — text-danger, так как он объявлен позже в CSS-файле Bootstrap."}
Raw{"answer": "text-primary", "пояснение": "В CSS при одинаковой специфичности классов последний объявленный в stylesheet-е (или более специфичный/важный, но здесь они равны по специфичности, а порядок в bootstrap.css определяет, что text-primary обычно следует за text-danger или они эквивалентны, однако в контексте вопроса подразумевается, что более поздний в коде/стилях или просто логика Bootstrap, где primary является стандартным, но технически если специфичность равна, выигрывает тот, что объявлен последним в файле стилей. Однако в Bootstrap 5 utility classes имеют одинаковую специфичность. Обычно в bootstrap.css классы упорядочены. Но есть нюанс: если вопрос предполагает "последний в теге", то это миф, CSS смотрит на порядок в CSS-файле. В bootstrap.css классы text-* идут в порядке: primary, secondary, success, info, warning, danger, light, dark, white, body. Значит text-danger объявлен ПОСЛЕ text-primary. Следовательно, должен выиграть text-danger. Подождите, проверим порядок в bootstrap.css. Порядок: .text-primary, .text-secondary, .text-success, .text-info, .text-warning, .text-danger, .text-light, .text-dark, .text-white, .text-body. Если text-danger объявлен после text-primary в CSS, то он должен переопределить text-primary при равной специфичности. Значит победитель text-danger. Однако в вопросе спрашивается "определи цвет", часто такие вопросы ловят на том, что оба применяются, но последний в CSS побеждает. В Bootstrap 5 порядок: primary (566), danger (594). Значит danger позже. Ответ должен быть text-danger. Но давайте проверим стандартное поведение или "ловушку". Если пользователь думает, что последний в теге побеждает, он ошибется. Правильный ответ — text-danger, так как он объявлен позже в CSS-файле Bootstrap."} | верно парсинг: текст (фолбэк) | Специфичность равна — победит правило позже в css: text-danger объявлен после text-primary. |
T25-L9 0.6 c | Чистая архитектура | Слои: Domain, Application, Infrastructure. Правила deptrac: Application → Domain; Infrastructure → Domain, Application; Domain → только Domain.
Сколько нарушений (Violations) покажет deptrac для этого класса?
```php
namespace App\Domain;
use App\Application\PlaceOrder;
use App\Infrastructure\Db;
class OrderService
{
public function __construct(
private PlaceOrder $handler,
private Db $db,
) {}
}
``` | «2» Пояснение: Класс находится в слое Domain, который по правилам может зависеть только от самого Domain, но использует классы из слоев Application (PlaceOrder) и Infrastructure (Db), что является двумя нарушениями.
Raw{ ⏎ "answer": 2, ⏎ "пояснение": "Класс находится в слое Domain, который по правилам может зависеть только от самого Domain, но использует классы из слоев Application (PlaceOrder) и Infrastructure (Db), что является двумя нарушениями." ⏎ } | верно | Domain может зависеть только от Domain: PlaceOrder (Application) + Db (Infrastructure) = 2. |
T25-L10 0.46 c | Чистая архитектура | Слои: Domain, Application, Infrastructure. Правила deptrac: Application → Domain; Infrastructure → Domain, Application; Domain → только Domain.
Сколько нарушений (Violations) покажет deptrac для этого класса?
```php
namespace App\Domain;
use App\Application\PlaceOrder;
use App\Infrastructure\Db;
class BillingService
{
public function __construct(
private PlaceOrder $handler,
private Db $db,
private \App\Infrastructure\Logger $logger,
) {}
}
``` | «3» Пояснение: Класс из слоя Domain импортирует классы из слоев Application и Infrastructure (2 разных слоя), что нарушает правило разрешенных зависимостей для слоя Domain.
Raw{"answer": 3, "пояснение": "Класс из слоя Domain импортирует классы из слоев Application и Infrastructure (2 разных слоя), что нарушает правило разрешенных зависимостей для слоя Domain."} | верно | Inline-FQCN \App\Infrastructure\Logger тоже считается: Application + Db + Logger = 3. |
T26-L10 0.43 c | DDD | Что выведет этот код?
```php
final class Money
{
public function __construct(public readonly int $amount) {}
public function add(Money $o): Money
{
return new self($this->amount + $o->amount);
}
}
$a = new Money(10);
$c = $a->add(new Money(5));
echo $a->amount . ',' . $c->amount;
``` | «10,15» Пояснение: Метод add создает новый объект Money с суммой 15, не изменяя исходный объект $a.
Raw{"answer": "10,15", "пояснение": "Метод add создает новый объект Money с суммой 15, не изменяя исходный объект $a."} | верно | VO иммутабелен: add() возвращает новый инстанс, исходный не меняется. |
T26-L9 0.46 c | DDD | Что выведет этот код?
```php
final class Order
{
private array $items = [];
public function add(string $sku): void
{
$this->items[$sku] = true;
}
public function count(): int
{
return count($this->items);
}
public function remove(string $sku): void
{
if (count($this->items) === 1) {
throw new DomainException('last item');
}
unset($this->items[$sku]);
}
}
$o = new Order;
$o->add('a');
try {
$o->remove('a');
} catch (DomainException) {
}
echo $o->count();
``` | «0» Пояснение: Метод remove вызывает unset перед выбрасыванием исключения, поэтому массив items становится пустым.
Raw{"answer": 0, "пояснение": "Метод remove вызывает unset перед выбрасыванием исключения, поэтому массив items становится пустым."} | неверно верный: «1» | Сорванный remove не меняет состояние агрегата: инвариант бросил исключение до unset — count остался 1. |
VC-L9 0.33 c | PHP 8.4–8.5 | Что выведет этот код на PHP 8.5?
```php
class C
{
public function hi(): string { return 'hi'; }
}
echo new C()->hi();
``` | «hi» Пояснение: Метод hi() класса C возвращает строку 'hi', которая выводится функцией echo.
Raw{"answer": "hi", "пояснение": "Метод hi() класса C возвращает строку 'hi', которая выводится функцией echo."} | верно | С 8.4 new в цепочке методов вызывается без обрамляющих скобок. |
VC-L10 1.59 c | PHP 8.4–8.5 | Что выведет этот код на PHP 8.5?
```php
class Heavy
{
public int $v = 0;
}
$r = new ReflectionClass(Heavy::class);
$o = $r->newLazyGhost(function (Heavy $obj) {
$obj->v = 21;
});
echo $r->isUninitializedLazyObject($o) ? 'yes' : 'no';
$o->v;
echo $r->isUninitializedLazyObject($o) ? 'yes' : 'no';
``` | «yesyes» Пояснение: Сначала объект является lazy ghost ('yes'), после обращения к свойству $o->v он инициализируется и перестает быть ghost ('yes' не вернется, но в коде второй echo выведет 'no', однако в примере ответа требуется строка результата выполнения, которая будет 'yesno' в случае правильного понимания, но я ошибся в формулировке ответа. Давайте перепроверим: 1. isUninitializedLazyObject($o) до доступа к свойству -> true -> 'yes'. 2. $o->v вызывает callback. 3. isUninitializedLazyObject($o) после доступа -> false -> 'no'. Итого 'yesno'. Но в задании просят строку. Я укажу 'yesno'.
Raw{"answer": "yesyes", "пояснение": "Сначала объект является lazy ghost ('yes'), после обращения к свойству $o->v он инициализируется и перестает быть ghost ('yes' не вернется, но в коде второй echo выведет 'no', однако в примере ответа требуется строка результата выполнения, которая будет 'yesno' в случае правильного понимания, но я ошибся в формулировке ответа. Давайте перепроверим: 1. isUninitializedLazyObject($o) до доступа к свойству -> true -> 'yes'. 2. $o->v вызывает callback. 3. isUninitializedLazyObject($o) после доступа -> false -> 'no'. Итого 'yesno'. Но в задании просят строку. Я укажу 'yesno'."} | неверно верный: «yesno» | newLazyGhost (8.4): объект ленив, пока к нему не обратились — чтение свойства инициализирует и снимает флаг. |
T28-L9 0.38 c | Symfony: версии | Проект обновлён с Symfony 6.4 на 8.1. Что выведет этот код на 8.1?
```php
echo class_exists(\Symfony\Component\Security\Guard\AbstractGuardAuthenticator::class)
? 'yes' : 'no';
``` | «no» Пояснение: Класс AbstractGuardAuthenticator был удален в Symfony 5.3 и недоступен в Symfony 8.1.
Raw{"answer": "no", "пояснение": "Класс AbstractGuardAuthenticator был удален в Symfony 5.3 и недоступен в Symfony 8.1."} | верно | Guard-аутентификация удалена в Symfony 7.0 — класса в 8.1 нет. |
T28-L10 0.43 c | Symfony: версии | Проект обновлён с Symfony 6.4 на 8.1. Что выведет этот код на 8.1?
```php
echo class_exists(\Symfony\Component\Routing\Loader\AnnotationClassLoader::class)
? 'yes' : 'no';
echo class_exists(\Symfony\Component\Routing\Loader\AttributeClassLoader::class)
? 'yes' : 'no';
``` | «noyes» Пояснение: В Symfony 7+ класс AnnotationClassLoader удалён, а AttributeClassLoader является стандартным для загрузки маршрутов через атрибуты.
Raw{"answer": "noyes", "пояснение": "В Symfony 7+ класс AnnotationClassLoader удалён, а AttributeClassLoader является стандартным для загрузки маршрутов через атрибуты."} | верно | Аннотационные лоадеры удалены в 7.0, остались атрибутные (Annotation→Attribute). |