Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757
Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770 Форумы портала PHP.SU :: Версия для печати :: PHP Test by PHP.SU
Увидел здесь некоторые вопросы, на которые и сам в свое время на форуме давал ответы. Можно продолжить. Своей страницы у меня нет, но все же напишу здесь. Важно - попробуйте ответить, не используя сэндбоксы и не проверяя результат скриптом - так результат теста будет гораздо актуальнее. 0. Что будет результатом:
Произойдет фатальная ошибка, т.к. Closure - служебный класс для реализации замыканий и он объявлен как final (финальный), таким образом от него нельзя наследовать.
1. Напишите функцию get_var_name, которая определяла бы название переменной. То есть:
Вернет строку "test" с числом ссылок, равным 2. 2 будет потому, что в PHP реализован метод организации памяти "copy-on-write". И если существует единственная ссылка на переменную, PHP оптимизирует метод, которым она передается в функцию. Внутренне, PHP рассматривает $sTest как ссылку (таким образом refcount увеличивается для области видимости функции), при условии, что если в переданную ссылку придется производить запись, то создается копия, но только в момент записи
Результат будет 2. Постинкремент сохраняет старое значение во временную переменную, увеличивает переданную по ссылке переменную, но возвращает старое значение.
Таким образом, на этапе присваивания $a уже равна 3, но инкремент вернул значение 2, которым и перезаписывается переменная, становясь равной вновь 2.
Destructed - так как деструктор вызовется даже в случае наличия exit() и подобных конструкций.
9. Дана таблица в SQL, имеющая 2 колонки - value (VARCHAR) и repeat_count (INT). Напишите запрос, результатом которого будет такое множество строк, чтобы каждое значение value повторилось в нём ровно repeat_count раз. Использование хранимых процедур не допускается. Использование СУБД-зависимых особенностей (вроде оператора присваивания для MySQL или PARTITION-особенностей, т.к. версия СУБД заранее неизвестна) - не допускается. Пример:
Результат будет NULL и Notice, сообщающий о необъявленной переменной $this. Связано это с тем, что хоть $this и является особенной внутри класса, тем не менее мы объявили ее как статическую, а потому такое именование допустимо в классе. Тем не менее, в скрипте, где мы её вызываем, $this по-прежнему имеет особенность, вследствие чего не может считаться объявленной.
11. В чем отличие и есть ли оно в использовании use и global в замыканиях?
use передает контекст (то есть данные на момент объявления замыкания), а global передает данные глобального пространства - независимо от того, когда и где было объявлено замыкание. Кроме этого, global может переопределять переменные в use, если и use и global используются вместе.
12. Все ли типы данных допустимы для type-hinting? Если не все, то какие запрещены?
15. Дана архитектура - есть 2 сервера A и B, на которых размещен некоторый проект. На обоих размещено одно и то же PHP-приложение. Есть некоторый балансер C. Когда пользователь запрашивает страницу на веб-сайте, запрос приходит к C и затем он, рандомно выбирая 0 или 1 - отправляет запрос, соответственно, на A или B. Серверы A и B используют одну и ту же БД, располагающуюся на сервере D. Все работало хорошо, но потребовалось сделать часть для авторизованных пользователей. Разработчики предоставили такой функционал, но возникла проблема: пользователь при авторизации стартовал сессию на одном из серверов A или B (в зависимости от того, куда был послан запрос сервером C) - и при повторном действии уже в личном кабинете, запрос мог уйти на тот сервер, на котором сессия пользователя не была запущена. Соответственно, происходил выход из личного кабинета. Как можно решить эту проблему. Оценивается: быстродействие, минимальность вмешательства в код приложения, минимальная сложность решения как с точки зрения сетевой инфраструктуры, так и с точки зрения общего устройства.
17. Дана таблица. Её поля id (INT) и value (VARCHAR). Напишите запрос, который удвоит id тех строк этой таблицы, у которых name принадлежит заданному списку значений A0, A1... An. (предполагается, что нет никаких CONSTRAINT ни на одном из полей таблицы, так что уникальность результирующих id не требуется)
18. Имеется php-скрипт, который предполагается к исполнению как системный сервис ("демон"). Возможна ли передача параметров уже работающему скрипту? Если нет, то почему? Если да, то как можно модифицировать скрипт так, чтобы он принимал параметры, будучи уже запущенным?
19. В чем отличие использования PHP как модуля от использования его в режиме CGI? А для FastCGI? Если есть разница, опишите. Напишите преимущества и недостатки всех трех способов организации.
CGI плох в основном тем, что каждый раз веб-сервер взаимодействует с исполняемым файлом php; тот, в свою очередь, загружает(перечитывает) php.ini, все свои модули (такие как php_mysql, php_mbstring и т.п.) - то есть много накладной работы каждый раз. Это, правда, может рассматриваться и как преимущество - ведь для изменения параметров PHP достаточно изменить php.ini и веб-сервер уже не нужно перезапускать, т.к. при следующем исполнении скрипта php.ini перечитается. Однако если важна скорость, то загрузка php как модуля веб-сервера дает преимущество.
FastCGI - это когда интерпретатор, один раз запустившись ждет когда ему "дадут работу", и не выгружается из памяти, присутствую там в виде демона слушающего порт/сокет.
Естественно после изменения php.ini перезапускать нужно, но не веб-сервер, а сам php.
Итоги очевидны сами собой. Модуль - это быстродействие, CGI - гибкость. FastCGI сочетает и то и другое, но каждое в меньшей степени.
наглядно покажет разницу. Код выше для unset сообщит Notice о необъявленной переменной, тогда как в случае установки null его не будет; в обоих случаях покажется NULL как результат
Фатальная ошибка. Недопустимо использование разделителей (пробелов, табуляций и т.п.) в строке-терминаторе HEREDOC
23. Существует ли ограничение на число триггеров одного события и времени на таблице? То есть, к примеру, сколько триггеров может быть BEFORE INSERT? Уточнение: СУБД - MySQL
в MySQL - только 1 триггер на событие одного времени наступления
24. Исполняются ли триггеры при неявном наступлении события, на которое они созданы? (Так, например, если есть триггер BEFORE INSERT - сработает ли он при LOAD DATA?) Уточнение: СУБД - MySQL
Формально да. Однако есть одна тонкость. Например, LOAD DATA действительно вызовет триггер на INSERT, тогда как TRUNCATE не вызовет триггер на DELETE (так как действия разные)
В том, что в первом случае функция вызывает сама себя, а во втором - она вызывается в связке с другими функциями. Рекурсивный вызов конструктора - пример неявной рекурсии.
Segmentation fault
Почему? Потому что нужно придумать что-то получше, чем вызывать конструктор в деструкторе.
30. Предположим, что HOST, USER, PASSWORD - данные для правильного MySQL - соединения; DB, TABLE, FIELD - указывают на существующую БД,таблицу и поле. Что произойдет:
Данные выведутся из БД корректно, однако mysql_close() породит предупреждение, т.к. $rLink будет иметь логический тип. Связано это с использованием оператора || - который возвратит $rLink как результат логического или указанных в нём выражений. В этом примере видна неидентичность || и or
Произойдет вызов исключения с сообщением 'another test here' - ведь, несмотря на успешное исполнение когда в блоке try, выполнится условие для блока catch
true - поскольку isset или empty должен вызвать __isset, на основании которого уже вернуть результат. empty вызовет геттер только в случае, если __isset вернет true (разумеется, он должен присутствовать), isset же не вызовет геттер в любом случае.
За каждый вопрос дается от 0 до 2 баллов (в зависимости от степени полноты и корректности ответа). Среди вопросов встречаются вопросы-шутки. Вам решать, отвечать на них (к тому же я не говорю, какие именно вопросы), или нет, но они включены, так как возникали в действительности (просто ответ на них можно рассматривать как юмористический).
Если вы набрали более 90%, то вы очень хорошо знаете веб-программирование на PHP (по моей субъективной оценке).
0) не вспомнил, кто такой класс Closure
1-2) -
3) true, т.к. instance of смотрит всё дерево наследования.
4) 2. $var++ возвращает значение переменной до увеличения значения. И переменной перезаписывается её старое значение, вместо уже увеличенного инкрементом.
5) ответил неверно
6) null / false, не помню, что get_parent_class отдаёт. Класс не наследует другой класс, а реализует интерфейс, потому родительского класса не имеет.
7) ответил неверно
8) Destructed. При завершении скрипта деструктор вызывается автоматически. Однако, если мне не изменяет память - при критических ошибках деструкторы могут не отработать и полагаться на них не стоит.
9) select repeat(`value`, `repeat_count`) from `tbl`
Возможно, неверно понял задачу.
10) fatal error, видимо, а вот на каком этапе - без запуска не знаю.
11) global - берёт переменную на момент вызова, use - на момент объявления замыкания.
И по-умолчанию use - по значению передаётся, а global может переопределить use.
12) не все, точный список боюсь наврать, но преобразования массива к числу точно запрещены.
13) уровень генерируемой ошибки, warning для include и fatal для require. В остальном - синонимы.
14) -
15) пути решения вижу 2:
а) делать доступными общими сами сессии между узлами
б) указывать балансеру правило для пересылки на конкретный узел запроса
Первый - DRBD как вариант невмешательства в код вовсе, но не слишком либерально по производительности.
Второй - пихать в идентификатор сессии / куку id узла и, если они есть, роутить запрос на указанный узел - пострадает корректная балансировка
0. Думаю, что это зависит от того, описан ли __call() в Closure.
3. true потому что класс-наследник считается instanceof родителя.
4. 2 - сначала присваивание, потом постфиксный инкр.
5. Будет ошибка о несуществующем статическом свойстве. Почему - вероятно, потому что оно не существует)
6. false (тут я слазил на php.net посмотреть что возвращает функция, если родительских классов нет. php.net же не возбраняется? )
7. Ошибка о переопределении константы.
9.
select value
from (
select
value, row_number() over(partition by value order by 1)rn, repeat_count
from tbl
cross join (values(1),(1),(1),(1))t(c)
)t
where rn <= repeat_count
Это с синтаксисом MS SQL Server, а в Mysql row_number можно заменить на подзапрос (count(*) where inner.number < outer.number). И такой же кросс жойн. number можно так получить
select *, @i := @i + 1 number from tbl cross join (select @i = 0 d)d
10. Могу подумать что фатальная ошибка, потому что использование $this всне объекта, могу подумать, что всё ок, поскольку элемент $this есть в классе. Могу подумать, что что-то еще, т.к. переменная $this - не простая)
12. Не знаю. Воможно, запрещены ресурсы.
13. Первый в случае отстутсвия дает фатал еррор, первый - ворнинг
15.
- Хранение сессий в общей базе.
- Придумать механизь синхронного создания/удаления сессий на обоих компах
- Доверить авторизацию фронт-енд серверу, а остальным он пусть передает сведенья об авторизации, добавляя их в гет-запрос(возможно, это бред )
16. Всё должно начинаться с буквы или подчеркивания.
17. update tbl t1 natural join tbl t2 set t1.id = t2.id*2 where name in(...)
18. Сходу скажу, что можно через файл или БД или другой разделяемый источник данных. Соответственно скрипт должен его мониторить.
19. Тут я не силен, но как модуль будет меньше потребляться памяти, и все будет запускаться от юзера апача. CGI вроде можно запускать из-под разных пользователей и по-разному ограничивать права. Плюс каждый отдельный скрипт может падать не мешая другим.
20. NAN
21.Разница в том, что при присваивании нулл переменная останется установленной. ис_сет на такую переменную даст тру.
22. Если пробел перед точкой с запятой - опечатка, то стринг. Вокруг закрывающей штуковины хередока не должно быть пробелов, иначе будет синт.ош.
23. В мускуле - только по одному. В файрберде - несколько.
25. Вечный цикл, потому что бару присваивается не-фуу, а фуу остается чем был.
26. В чем разница между явной и неявной рекурсией? Приведите пример того и другого в PHP.
Наверное в том ,что в случае явной рекурсии функция вызыват саму себя сама, а в случае неявной, функция А вызывает Б, Б вызывает Ц, а Ц вызывает А.
Пример написать лень)
27. Будет массив, но как изобразится его индекс - не знаю.
28. Ресурс нельзя
(Добавление)
Некоторые вопросы нагнали меня на новый вопрос.
Выделил в новую тему Champion
В задаче номер 9 я сделал уточнение - нельзя использовать СУБД-зависимые особенности (вроде оператора присваивания) (Добавление)
Добавил те ответы, которые нашел.
Дополнил ответы.
Предлагаю наиболее сложные и интересные вопросы писать в эту тему. Я позже дополню тест. Очень желательно, чтобы это было ситуацией "из жизни", так как разбирать абстрактные, созданные специально для теста, ситуации - не столь интересно.
16) Объявлять методы - нельзя. Вызывать - возможно.
class A {
public function __call($name, $arg) {
var_dump($name, $arg);
}
}
$Q = new A;
$Q->{'123'}();
Аналогично, через магические методы и любые имена свойств можно менять.
К слову, запросто можно получить с виду невалидные имена свойств при разборе XML, тоже поле e-mail.
17) Для моего словарного запаса "принадлежит заданному списку значений" - это in (список значений). Вероятно, вновь неверно понял задачу, т.к. получается простейший апдейт.
18) Возможно. Решение в лоб - с заданной периодичностью проверять файл, сокет.
19) модуль - только апач, php запускается вмместе с апачом и так и живёт.
CGI - стандартный протокол, поддерживается практически всеми веб-серверами. Однако запуск php происходит на каждом обращении к скрипту.
fastCGI - демон, работающий по CGI, но держащий готовый к работе php постоянно.
20) не числовой тип - точно, что возвращает sqrt при ошибке - не помню
21) При присвоении null'а переменная остаётся в области видимости, не вызывает E_NOTICE при обращении и съедает свои несколько десятков байт.
unset же именно удаляет переменную.
22) string. Разве есть другие варианты?
23) вроде бы нет
24) на сколько помню мануал - нет, не выполнятся.
25) define присваивает константе конкретное значение, полученное при выполнении второго аргумента, а не выполняет конструкцию при обращении к константе. Поэтому цикл бесконечен.
26) явная - когда функция вызывает саму себя, так прям в коде функции и прописан вызов.
function foo() {foo();}
неявная - например, цикличный вызов 2 или больше функций. Хотя может неверно помню определение.
function foo() {bar();}
function bar() {foo();}
27) предполагаю, что всё ок, массив и ключ создастся. Получить к нему доступ может быть непросто.
28) ресурсы (gd, curl, файловые дескрипторы) не сериализуются. А если всё-таки да - то обратно не распаковываются.
29) отличный вопрос
Это произойдет потому, что пост-инкремент применится после присваивания
Не согласен с пояснением. Постинкремент сохраняет старое значение во временную переменную, увеличивает переданную по ссылке переменную, но возвращает старое значение.
Таким образом, на этапе присваивания $a уже равна 3, но инкремент вернул значение 2, которым и перезаписывается переменная, становясь равной вновь 2.
EuGen пишет:
Фатальная ошибка - недопустимо переопределять константы, даже если речь идет о реализации интерфейса.
Именно если речь идёт об интерфейсе.
class foo {
const bar=1;
}
class footoo extends foo {
const bar=2;
}
var_dump(footoo::bar, foo::bar);
EuGen пишет:
В первом случае уничтожится и указатель на переменную, во втором - только значение. Поведение функций вроде isset() отличается сообразно этому.
isset ведёт себя идентично в обоих случаях.
EuGen пишет:
Фатальная ошибка. Недопустимо использование разделителей (пробелов, табуляций и т.п.) в строке-терминаторе HEREDOC
Это подло! Я на лету поправил ошибку и проигнорировал пробел.
Мелкий
Насчет инкремента - дополнил. Мой комментарий не раскрывает до конца сути происходящего, потому заменил пояснение на Ваше.
Про интерфейсы и константы - опечатка в слове "даже", исправлено
isset - вопрос. Вероятно, вопрос версий? Я поэкспериментирую. Если дело в версии, то уберу из пояснения (т.к. вносит неоднозначность).
Про HEREDOC - в том и смысл. В реально возникшей ситуации достаточно долго пришлось разбирать, где же ошибка.
Мелкий
Про isset - верно, даже на 5.3 я увидел одно и то же. Поправил комментарий, внеся пример с реальным отличием.
Насчет IDE - они бывают разные, суть от этого неизменна.
Мелкий, EuGen, решения интересные, я даже не знал таких возможностей. Впрочем, я много чего не знаю)
Но Мелкий, как сам сказал, только 5.4, а classkit_method_add не включен в стандартную поставку PHP как я понял.
Я предполагал решение с serialize + preg_replace + unserialize. Где это применимо - не знаю. Просто в голову пришло)