Пользователь
0,0
рейтинг
3 апреля 2012 в 11:16

Разработка → PHP. Собеседование в вопросах и ответах

PHP*
imageНекто Андрей Шевченко составил, структурировал и выпустил в виде бесплатной PDF книги список вопросов, которые всенепрменнно могут встретится(и чаще всего встречаются) любому PHP программисту на самом стандартном собеседовании. Более того — каждый вопрос снабжен достаточно подробным ответом.

Пролистать книгу будет полезно любому PHP программисту, который планирует вскоре быть отсобеседованным, либо же людям, собеседующим соискателей.

Прямая ссылка на книгу.
Сайт книги.

(я не автор данной книги, просто спешу поделиться, т.к. она показалась мне полезной)

upd
На Хабре обнаружился автор.
Поляков Павел @Zaido
карма
23,3
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (432)

  • +33
    Такое ощущение, что сейчас это тред – учиться проходить собеседования, а не программировать. Знать ответы на вопросы собеседования, но не применить их на практике ни разу.
    Я видел собеседования, где программисты не могли сказать, чем отличается объект от класса, процедурный подход от объектно-ориентированного. Вот, что важно.

    Я нисколько не умаляю информации в этой книге, я просто не очень доволен ситуацией в области.
    • +13
      скоро будут агентства, которые будут за Вас ходить на собеседование, а может и кодить :)
      • 0
        Спрос порождает предложение.
      • +5
        Почему бы и нет? На «эстраде» у нас уже давным-давно такая ситуация.
        тьфу-тьфу-тьфу, конечно
      • +64
        Анекдот в тему:

        Нанимает американский генерал летчиков на работу. Заходит немец.
        Рассказывает, сколько налетал, в каких операциях участвовал.
        Генерал спрашивает:
        — А сколько ты хочешь получать?
        — 3 тысячи долларов.
        — А на что ты их потратишь?
        — Ну как? Одну в банк положу, одну — семье, одну себе.
        Заходит англичанин. Тоже рассказывает, сколько налетал, в каких
        операциях участвовал.
        — А сколько ты хочешь получать?
        — 4 тысячи долларов.
        — А на что ты их потратишь?
        — Ну как? Одну в банк положу, две — семье, одну себе.
        Заходит русский. Генерал спрашивает:
        — Сколько налетал?
        — Нисколько.
        — ???
        — В каких операциях участвовал?
        — Ни в каких.
        — ???!!!
        — А сколько получать хочешь?
        — 9 тысяч.
        — А зачем тебе столько?
        — Ну как? Три — Вам. Три — себе. А за три немец летать
        согласился.
        • –10
          Я бы поменял здесь русского на еврея.
      • +1
        Так в был же пост недавно вроде, в Британии агенты ходят за тебя.
        • 0
          Они не собеседуются, они назначают встречу работнику с работодателем.
      • +8
        Как в анекдоте: «Три тыщи Вам, три мне, а за тыщу согласен индус работать».
        • +2
          Эх, не обновил страницу перед отправкой.
    • 0
      Зато по ответам можно будет определить, понимает ли человек, о чем говорит, или просто вызубрил книгу.
    • +2
      Учиться проходить собеседования надо :(
    • +4
      меня несколько удивляет и то, как многие конторы проводят собеседования — задавая вопросы о том, чего в работе и близко не используют. поэтому часто главное собеседование пройти — а работать сможешь
      • +1
        это да
    • +1
      в книге как раз и написаны ответы на вопросы типа «чем отличается объект от класса, процедурный подход от объектно-ориентированного» :)
    • +3
      Просто прохождение собеседования часто зависит не от навыков программирования, а от социальных навыков. Тебя могут завернуть, если ты, там, вяло руку рекрутеру пожал, или смело в глаза не смотрел.
      Или задаются пространные вопросы типа чем отличается php 5.3 от php 5.2.

      Нафига? Человек должен понимать код, писать код, уметь правильно мыслить и уметь учиться (или гуглить). Всё. Я встречал туеву кучу людей, которые блестяще проходили собеседование на php программиста, приходили на рабочее место и сдувались, потому что блестящая теория не давала им бонуса к практике.

      Вот по себе скажу — если мне вопрос зададут, я не смогу, например, ответить чем ООП отличается от процедурного метода. Тем не менее в мозгах я это понимаю и одинаково хорошо пишу как в одном так и в ином направлении. Но на вопрос не отвечу. Потому что думаю не так.

      Как то так, вот…
      • 0
        этой фигней страдают ху… хантеры, они только обеспечивают поток людей на вакансию. 70% завернуть можно сразу, остальные будут представлять хоть какой-то интерес.
      • 0
        По-этому я предпочитаю перед собеседованием принять на душу=)
      • 0
        пространные вопросы типа чем отличается php 5.3 от php 5.2.


        Я этот вопрос задаю на собеседовании, что бы понять на сколько человеку интересно то чем он занимается. Если человеку действительно интересно, то он постоянно следит за новинками в области, а потом подходит к руководству и говорит: «Надо на нашем выделенном сервере обновить php и я даже готов исправить все баги на всех наших 5-10 сайтах, которые всплывут после перехода. Зато, я больше времени сэкономлю используя современные технологии». Но если человек ходит на работу ради ЗП и молча делает всё то что ему приказывают, то ему новые технологии до лампочки и тем более он не будет изучать: ООП, паттерны, tdd,…
        • 0
          Главное — писать код, который будет работать без сбоев. Если будет участок работ, где система, скажем, будет в разы стабильнее работать без ООП — глупостью будет стремиться за новинками в ущерб стабильности и производительности.

          Поэтому более интересным был бы вопрос не в разнице версий, а, скажем «какую бы вы предложили версию для реализации %problemName% и почему?».
          имхо.
          • +1
            какую бы вы предложили версию для реализации %problemName% и почему?.

            Для всех возможных задач правильным ответом будет: «самую последнюю» (php 5.4). Почему бы и нет? Не вижу смысла использовать старые динозавры.
            А вы можете придумать задачу для решения которой лучше было бы использовать старое древнее php4?

            Вы не поверите сколько php-программистов не могут ответить на вопрос «какая самая последняя стабильная версия пхп?», потому что им пофиг — им лишь бы быстрее дожить до выходных, получить ЗП и пойти в бар с друзьями.
            • 0
              Я вот например не знал, что последняя — 5.4
              Потому что до сих пор у всех заказчиков — 5.2 и менять не собираются. И только один из последних заказов проскочил — переписать 5.2 на 5.3

              В конце концов, если вы — компания, где рядовой программист может прийти, сказать «а давайте обновимся, адаптация — с меня» и компания бесспорно согласится, то вы — очень дружелюбная к разработчику компания. Сочтите за комплимент. ))

              Да и вообще — писать код чтобы дожить до выходных — я такого отказываюсь понимать. Это должен быть или очень скучный вялотекущий проект, или сотрудник, которому не нравится работа. По первому вопросу — стоит рассмотреть возможность заинтересовать сотрудника, по второму… Второй вообще как бы удивляет — такого человека и принять то не должны были. Или убрать если всё так плохо. Но он есть. Где собака порылась — непонятно.
              • 0
                Может выбирать особо не из чего, а проект(ы) малоинтересные, вот работа и не нравится.
        • 0
          А я вот толком не помню уже, что изменилось в 5.3 — давно это было. Особенно в плане потери обратной совместимости нюансы. Так-то глобально можно сказать — нэймспэйсы, анонимные функции, замыкания, сборщик циклических ссылок. А вот посмотрел список и вижу что многое забыл, например: goto (про него вообще забыл :) ), LSB (казалось что в 5.2 он уже был), константы в глобальном нэймспейсе, ?:, и т. п. В общем я сейчас озабочен совместимостью своего 5.3 кода с 5.4, чем с 5.2.

          Не пройду ваше собеседование?
          • 0
            Пройдёте :) goto — зло, по этому хорошо что про него забыли. Наизусть учат когда готовятся к собеседованию по таким книжкам. Изменений в php5.3 было очень много — запомнить всё не возможно, да и было это 3 (!!!) года назад.
            • 0
              Когда мне на собеседовании озвучивают что «Goto зло»
              У меня сразу возникает куча вопросов
              1. «А вот объяснить почему оно зло можете?»
              Ну или давайте с другого конца —
              2. «Вы используете break для прерывания цикла?»
              или вот еще
              3. «Как часто в методах и функциях которые вы пишите вы используете больше одного return?»
              и последнее
              4. «а причем здесь goto?»

              И break, continue, goto а также «несколько точек выхода из метода (return)» нарушают принципы структурного программирования.
              Когда люди во всю нарушая принципы структурности в своем коде, говорят что «goto зло» мне это напоминает курильщиков марихуанны, которые ратуют за смертную казнь наркоманам.
              Continue break — ИМХО удобны и полезны больше чем вредны
              множественный выход из функции — вреден почти всегда (например чтобы добавить логгер перед завершением метода придется копипастить его перед каждым return), в поддержку него можно только назвать проверка входных данных и выход до основного блока
              goto — после того как ввели break а некоторых языках и break N то придумать хоть какую нибудь задачу где он был бы полезен стало мягко говоря проблематично

              Я это к чему веду. Если человек голословно заявит при мне что goto зло, но при этом не может объяснить почему — то сие заявление я скорее запишу ему в минус чем в плюс
              • 0
                это применимо не только к goto, а к абсолютно любому утверждению. я вообще-то всегда считал, что любые однозначные/категоричные утверждения, которые не могут быть хоть немного внятно объяснены — это минус.
                есть даже шутка-мысль такая — чем меньше человек делает категоричных заявлений, тем менее смешно он выглядит в будущем.
  • +10
    == 3. Какими способами можно перенаправить страницу в PHP?
    кроме двух указанных есть ещё один через meta refresh

    == 13. Обязательно ли писать ?> в конце скрипта?
    Так как есть завязка на пхп версии 4, то этот ответ имеет два варианта, а не один, как указано
    в пыхе 4.х обязательно

    == 17. Какая разница между функциями echo и print в PHP?
    echo не функция, а часть языка (statement), print функция.

    и вобще ответы устаревшие по отношению к 5.3… 5.4

    но если честно, вопросы по мануалу, а их редко задают
    • +4
      Пролистав дальше: это какой-то шаблонный справочник совсем для нубов, в школе на экзаменах могут такие вопросы задавать, но не на собеседовании.
      • +11
        У вас в школе PHP преподавали? Мы дальше шестнадцатеричной системы не ушли.
        • 0
          В мои школьные года пхп не существовал в зачатках. Но нам преподавали, кажется, основы паскаля.
          • +1
            Его до сих пор преподают, хотя учителя большей частью сами толком программировать не могут.
          • 0
            вы закончили школу раньше 94 года?
            • 0
              позже. но писать, на каком там, пхп 3.0 было удовольствие как сайты на баше :)
              • 0
                Что и 4 даже не застали?
                • 0
                  в школе нет.
              • 0
                Это вы просто сайты на Си не писали. PHP3 был вполне нормальным процедурным языком, ориентированным на веб.
                • 0
                  Я на перле писал за то :) А сейчас вот переписываю часть сайта на плюсах.
                  • 0
                    Ну я выбирал между PHP3 и Perl, когда понял, что писать сайты на СИ как-то не очень правильно.
    • 0
      ==== 3. Какими способами можно перенаправить страницу в PHP?
      ==кроме двух указанных есть ещё один через meta refresh

      А еще есть заголовок Refresh
      • 0
        refresh это метатег
        а заголовок — location
          • +2
            wiki wiki… w3c
        • 0
          Если refresh-это всего лишь метатег, то что же означают слова «http-equiv» в его конструкции?

          Возможно, вы об этом забыли, но каждый метатег, определяемый через http-equiv, является аналогом одноименного заголовка HTTP.
          • 0
            ага вспомнил, я подумал что тот кому я ответил перепутал location с refresh
            ну тогда если не перепутал, получается есть еще один способ, заголовок location :)
            • 0
              Читай внимательнее!

              В книге были приведены два способа:
              1. Заголовок Location
              2. javascript

              romy4 добавил третий — meta refresh

              Я (тот, кому вы ответили) добавил четвертый — заголовок refresh

              Какой «еще один способ» вы нашли?
              • 0
                все верно. вам бы лишь бы придраться? я не читал эту книгу и не искал сколько там ответов дано
              • 0
                4 способ: meta http-equiv=«location»
                • 0
                  Да когда вы читать научитесь, для начала хотя бы тот комментарий, на который отвечаете.
                  Во-первых, это не 4 способ, а пятый!

                  А во-вторых, этот «способ» не работает (по крайней мере, в Chrome)
                  • +3
                    Ведь это же сто процентный тупняк вот вы спрашиваете у человека на с-нии
                    Какими способами можно перенаправить страницу в PHP?

                    а он тебе ответ:
                    2. Используя JavaScript…

                    по моему очень смешно
                    • 0
                      Не тупняк, а один из способов как можно перенаправить страницу в PHP.
                      • 0
                        ага с помощью ЯваСкрипта :) браво!!!
                        • 0
                          Это всего лишь один из нескольких способов.
                          • 0
                            это все шутка перво-апрельская? :) или это такой тонкий троллинг?
                            • 0
                              ну не толстый же!
    • +3
      Если уж придираться, то print тоже языковая конструкция, а не функция: print 'helo world';
      • 0
        Если уж так копать, то да. Но echo парсится как языковая конструкция (language token T_ECHO), а print как функция, что ищется в массиве функций области видимости global.
        • +5
          T_PRINT.
          • +1
            ы. вы правы совершенно.
            и в конечном итоге сводится к ZEND_ECHO_SPEC_TMP_HANDLER которая выводит переменную.
      • 0
        Чтите мануал на эту тему: http://php.net/manual/ru/reserved.keywords.php
        • +1
          Вы действительно это мне отвечаете? =)
          • 0
            Нет, конечно: )
      • 0
        придраться ко всему можно, было бы желание :)
    • 0
      > а часть языка (statement)
      функция в императивном ЯП это тоже statement. Print тоже не функция, они все конструкции языка.
    • 0
      == 25.
      Ряд Фибоначчи выводится за сложность O(2^n), хотя можно за O(n).
      • +2
        Это кстати хороший тест на инерцию мышления:
        24. Напишите рекурсивную ф-ю ХХХХ
        25. Напишите ф-ю Фибоначчи
        • 0
          Ну рекурсивно с динамикой, да.
      • 0
        Просто энное число Фибоначчи и вовсе за логарифмическое время можно посчитать.
        • +5
          И даже за константное, если точность не важна.
          • 0
            Спасибо, вы мне на весь вечер настроение подняли.
    • 0
      ua.php.net/manual/en/function.print.php Я просто на всякий случай здесь оставлю, почитайте описание, там черным по белому говорится что принт — не функция. И это в мануале.
      • +1
        да и сам интерпретатор такого же мнения
        $ php -a
        Interactive shell

        php > var_dump(function_exists('print'));
        bool(false)
      • 0
        чёрт, комент предыдущий не отправился. Да, вы правы. print сводится к вызову ZEND_ECHO_… в конечном итоге.
    • 0
      еще как задают
      • 0
        Это печельно, что такие вопросы порой являются порогом прохождения по вакансии.
        • 0
          печально, но это так :) что есть то есть.
  • +15
    Это не книга, а некий текст, завернутый в PDF. В книгах не бывает такого количества ошибок правописания.

    Обратите внимание на третий вопрос: «Какими способами можно перенаправить страницу в PHP?». Судя по ответу, подразумевается перенаправление браузера на другую страницу. Вопрос сформулирован некорректно.

    Мне это творение кажется низкокачественным.
    • +15
      Там не только грамматические ошибки.
      Вот к примеру еще такие вещи есть:

      Как задать красный цвет для всех элементов, имеющих класс red?
      .red { background-color:white; }
  • +2
    нашел вредный совет:

    21. А как перевернуть массив без функции array_reverse?
    Например, так:
    <?php
    $arr = array(‘h’, ‘e’, ‘l’, ‘l’, ‘o’);
    $reversed = array();
    for ($i=0; $i<count($arr); $i++) array_unshift($reversed, $arr[$i]);
    for ($i=0; $i<count($reversed); $i++) echo “$reversed[$i]”;
    ?>


    считать count($arr) в каждой итерации не ок.
    Да и вариант не оч человеческий выбран:
    for ($i=count($arr)-1; $i<=0; $i++) { $reversed[] = $arr[$i]; }
    • +13
      Для массива hello world это по-барабану, даже на массиве с тысячей элементов. Сложность count($arr) константная, а не линейная. На пикосекунду дольше, чем вызов переменной со значением размера.
      • +4
        Ну мне кажется что человек который так пишет в примерах будет использовать такой подход и в реальном коде.
      • +19
        минусующие сосните тунца, сперва разберитесь в исходниках пыха.

        PHP_FUNCTION(count) → zend_hash_num_elements() → return ht->nNumOfElements;
        • +8
          Да это ведь горе-оптимизаторы. У них запросы к базе без индексов в цикле, а тормозит из-за неправильного count.
          • +13
            И двойных кавычек, ага.
            • +1
              Кстати, КО подсказывает, что производительность двойных кавычек в новых версиях тоже изменилась, причём, судя по поведению токенайзера PHP, который выделяет токены в двойных кавычках, выражения внутри двойных кавычек теперь тоже компилируются заранее, а поэтому есть вероятность, что это будет работать быстрее. И это подтверждает, к примеру, такой тест:

              <?php
              define('NUM', 1000000);
              $start = microtime(true);
              for ($i = 0; $i < NUM; $i++);
              $for_time = microtime(true) - $start;
              
              $some_str = "Hello world!";
              
              echo "For loop time: " . round($for_time, 3) . " sec\n";
              
              $start = microtime(true);
              for ($i = 0; $i < NUM; $i++);
              echo "Empty stmt time (should be 0): " . round(microtime(true) - $start - $for_time, 3) . " sec\n";;
              
              $start = microtime(true);
              for ($i = 0; $i < NUM; $i++) {
              	"hello world $for_time $i $for_time $i $for_time $i $some_str $some_str";
              }
              echo "Double quotes: " . round(microtime(true) - $start - $for_time, 3) . " sec\n";
              
              $start = microtime(true);
              for ($i = 0; $i < NUM; $i++) {
              	'hello world ' . $for_time . ' ' . $i . ' ' . $for_time .' ' . $i . ' ' . $for_time . ' ' . $i . ' ' . $some_str . ' ' . $some_str;
              }
              echo "Single quotes: " . round(microtime(true) - $start - $for_time, 3) . " sec\n";
              


              Результаты:

              $ php bench.php 
              For loop time: 0.097 sec
              Empty stmt time (should be 0): -0.005 sec
              Double quotes: 2.183 sec
              Single quotes: 2.891 sec
              
              • +1
                Всегда использовал одинарные кавычки, не потому что они быстрее, а потому, что shift не надо нажимать.
              • 0
                Ваши тесты немного ошибочные. Дело не в разных кавычках, а в том, что в варианте с одинарными кавычками используется оператор конкантенации, из-за которого вы и получаете разницу в 0.7 сек. Если в варианте с двойными кавычками использовать ту же конкатенацию, то время выполнения двух вариантов должно сравняться.
                • 0
                  Не согласен, как раз и были очень известные тесты, в которых говорилось, что конкатенация быстрее интерполяции переменных в двойных кавычках. Моё утверждение было о том, что это более неверно, причём уже довольно давно.
                  • 0
                    А, ну да, с 2001 года многое изменилось :)
                  • 0
                    что это более неверно, причём уже довольно давно.

                    Да, эти тесты уж слишком известные. Когда уже их удалять с сервера.
                    Особо доверчивых после прочтения сложно переубедить, аргументы о замшелости статьи не помогают, трясти начинает, когда в качестве аргумента дают пруф на эту статью. А начальство переубеждать сложнее всего (было у меня с кавычками).
              • 0
                Любопытно.
                Если же уменьшить количество переменных до 4, то конкатенация и двойные кавычки выравниваются по скорости.
                Ещё уменьшить — конкатенация быстрее.

                PHP5.3.5
                • 0
                  Похоже на правду.
                  • 0
                    Резюмируя, как это часто бывает, правильны оба вывода сразу, каждый при своих условиях:
                    конкатенация в малых количествах быстрее переменных в двойных кавычках, однако с ростом числа участвующих переменных конкатенация оказывается медленнее.
        • 0
          Клева, можно не парица оказывается. Похоже ето знание ко мне пришло как в известной истории про «здесь так принято» :)
        • 0
          И все таки, как тогда обьяснить это?
          • 0
            просто переменная $num: поиск в массиве переменных, возврат значения
            count($data): поиск переменной $data, возврат значения $data, вызов count для $data, возврат к-ва элементов $data.

            в два раза больше действий
    • +1
      Там скорее будет проблема в array_unshift, нежели в чем-то другом
    • 0
      Хоть бы кто-нить написал про ошибку )
      Там же не $i++, а $i--
      • +4
        Чтобы не ошибаться — пишите так:
        for ($i = count($arr); $i--;} {
            $reversed[] = $arr[$i];
        }
        
        • +2
          for ($i=count($arr); $i-->0;)

          мне так больше нравится :) Как будто $i стремится к нулю )
      • 0
        Здрасьте! С какой стати там должно быть а $i-- ??
        • 0
          В моем варианте:

          for ($i=count($arr)-1; $i>=0; $i--) { $reversed[] = $arr[$i]; }

          Там еще и условие выхода не правильное )
  • +8
    Кажется пора очередной пост писать :)
    habrahabr.ru/post/21681/
    habrahabr.ru/post/67963/
  • 0
    Это действительно вопросы для собеседований? о_О В моем говноколледже спрашивали примерно то же на экзаменах, правда про C++.
  • +27
    • 0
      бывает :)))))))))
    • +2
      И это собеседование по PHP! :)
  • +2
    Если коротко, то устаревшая хрень…
    • 0
      Мал, что устаревшая, так ещё и не точная хрень…
    • +1
      Если еще короче, то просто хрень
  • 0
    > В чем различия между четвертой и пятой версиями PHP?
    Кажется уже пора спрашивать в чем отличие 5.4 от 5.3 и от 5.2.
    • 0
      пора, но некоторые до сих пор спрашивают отличие 5 от 4…
  • +1
    31. Нарисуй форму для отправки файла…
    Разве не корректней использовать move_upload_file вместо copy?
    • +1
      и корректно, и правильно. Человек будет забивать темп загруженными файлами делая copy.
      • +1
        Не будет. После завершения скрипта загруженные файлы, если они не были перемещены, неважно каким образом, будут подчищены сами.
        • 0
          Да, мой баг. Но copy делает лишнюю работу.
          • +1
            Какую? В случае, если tmp и хранилище на разных разделах, а это зачастую так и есть, работа будет производиться одинаковая.
            • +1
              Да нет, далеко не часто.
            • 0
              Я чаще встречал хостинги, где tmp для виртуалхоста лежит на том же диске, даже в директории юзера, который хостится. Использование общего tmp чревато дырами.
          • 0
            Разница:

            copy:
            1. копирует файл

            move_upload_file:
            1. проверяет этот файл есть?
            2. проверяет загружен ли он пхп через пост?
            3. копирует файл
            4. удаляет файл

            Чувствуете разницу кто делает лишнюю работу? Не говорите глупостей, просто достаточно перед тем как что-то написать, почитать _официальный_ мануал по пхп, для того чтоб увидеть разницу и не выглядеть как человек которому эта книга нужна.
            • 0
              1 вопрос, а насколько корректно использовать вместо них rename? В случае если файлы на одном и том же локальном диске — будет ли копирование? А если они на разных томах? Судя по Changelog-у здесь начиная с 5.3.1(win) и 4.3.3(linux) должно сработать.
              • 0
                использовать можно хоть побайтовое чтение собственным расширением, написанным на сях. только зачем? move_uploaded_file сам всё делает. или я неправильно понял вопрос? :)
                • 0
                  Ну если верить taliban-у, то move_uploaded_file всегда копирует файл. Если я правильно понимаю rename, то переименовывание файла должно быть существенно быстрее, нежели копирование (особенно если речь идёт о каких-либо больших файлах, к примеру видео).
                  • 0
                    А вы лучше не верьте, а смотрите исходники. Мой ответ чуть ниже.
              • 0
                Вот тут уже не вкурсе, но вообще как человек выше говорил все же уместней использовать move_upload_file, именно из-за проверки ее на загруженность через пост, чтоб не скопировать «подсунутый» файл.
            • +3
              Сталкивался с тем, что если скрипт заперт в DOC ROOT`е, то copy не сможет достать файл, а move_uploaded_file сможет.
              • +1
                Вот она, сермяжная правда!
    • 0
      move_uploaded_file лучше в целях безопасности вроде как.
    • 0
      не корректней.
      • 0
        Чего вдруг?
  • 0
    А как перевернуть массив без нее?
    Это как моя любимая задачка на строку-перевертыш.

    $arr = array(‘h’, ‘e’, ‘l’, ‘l’, ‘o’);
    
    for ($i = 0; $i < floor(count($arr)/2); $i++)
    {
        $tmp = $arr[$i];
        $arr[$i] = $arr[count($arr)-$i-1];
        $arr[count($arr)-$i-1] = $tmp;
    }
    
    • +2
      Вот, на мой взгляд, более элегантное решение:
      	$source = array( 50 , 40 , 30 , 20, 10);
      	$pieces = count($array)-1;
      	$reversed = array();
      	while($pieces >= 0) {
      		$reversed[] = $source[$pieces--];
      	}
      

      Результат:
      Array (
          [0] => 10
          [1] => 20
          [2] => 30
          [3] => 40
          [4] => 50
      )
      • 0
        Всё зависит от требований. Решение перед вашим зато памяти дополнительной потребляет лишь в размере одной временной переменной. А у вас второй массив в памяти.
        • +2
          Может быть, может быть. Но, скажу честно, от конструкции floor(count($arr)/2) меня почему-то передёрнуло.
          • +1
            в школе стандартные алгоритмы на паскале не реализовывали чтоли?
            Или, наоборот, поэтому и передернуло? :)
            • +1
              Таким примером можно показать что недавно использовал активно паскаль, а как сделать оптимальнее в php не знаешь.
            • 0
              В школе, вы удивитесь, мы писали на Ассемблере. Но это был «кружок для избранных», остальные с горем пополам осваивали Бэйсик.
          • +1
            Более того она будет вычисляться каждую итерацию, неоптимальненький ответ.
        • +1
          Совершенно верно. Идет расчет на расход памяти. В идеале еще можно сделать через SplFixedArray, но я посчитал это излишним.
      • +1
        Преимущества такого подхода:
        1. Минимум писанины
        2. Наглядность
        3. count() вычисляется всего один раз (в отличие от остальных примеров у автора и в комментариях)
        4. Всего одна математическая операция — декремент. Нет путаницы в вычислениях, не нужен дебаг.

        Я понимаю, что это микрозадача. Но по стилю её решения сразу видно какой реальный опыт имеется у человека за плечами и каким образом этот «стиль» может сказаться на его фактической работе.
        • 0
          3. count() не вычисляется, он уже хранится вычисленным. А функция просто его возвращает.

          Недостаток этого подхода: в случае массива в 20мб и выделенной памяти в 32мб — ваше решение упадёт, а решение выше, хоть с десятком каунтов, будет работать.

          Говорю же — всё зависит от требований и ограничений.
          • 0
            Теоретически — да. На практике с массивами по 20Мб я просто не сталкивался и ничего не могу сказать о нагрузке при таких операциях. И ещё сразу появилась мысль, что если внутри ворочаются такие массивы, то не всё хорошо с архитектурой самого приложения.
            • 0
              Я с вами совершенно согласен, что такие массивы это или кривота, или исключение из правил. Но я хотел указать на то, что «более элегантное» это оценка настолько качественная, что в отрыве от требований к решению использовать её стоит очень и очень осторожно :-)
            • 0
              Задачи бывают разные
              • 0
                Моё любопытство настаивает на примере подобной задачи =)
                • 0
                  Такие задачи носят не постоянный характер, но встречаются.
                  В данный момент занимаемся переносом данных из доморощенной CRM в Salesforce. Данные переносятся по филиалам, до 100+тыс клиентов. В БД есть клоны, необходимо при переносе их склеить, поиск идент по ФИО и телефонам. Данные по телефонам хранятся как ввели. С помощью SQL решаемо, но долго, оказалось дешевле загрузить все в массивы и сравнить.
                  • 0
                    Разделяй и властвуй.
                    Это я к тому, что решение данной конкретной задачи в рамках корпоративной системы на локальном сервере с парой гигов оперативы носит абсолютно банальный характер.
                    Другое дело — если мы работаем в рамках виртуального хостинга на довольно ограниченных ресурсах. По образу и подобию можно было бы представить перелив данных из морально устаревшего, но довольно крупного интернет-магазина на новую архитектуру.
                    Да, задачка не из разряда «2+3», но это уже боевые условия и боевые задачи, которые должны решаться исходя из тех ресурсов, которые имеются на данный момент. И практика показывает, что на каждую конкретную задачу есть не менее трёх очевидных путей решения, не говоря уже о нестандартных. И тут уже важно выбрать самый оптимальный из них, а не спорить о том, чей говнокод отработает быстрее.

                    Суть всех холиваров в том, что они абстрагированы от реальных условий. Кто элегантнее заебенит функцию или класс, кто при обработке огромных массивов данных на доли секунды превзойдёт своего предшественника — это просто пиписькомер. Каждый день в боевых условиях настоящий программист должен принимать решения — какой путь более оптимален с поправкой на реальное положение вещей. Если он принимает верные решения — это хороший программист. Если он не может удержать в своём сознании все связи классов и модулей, не может хотя бы приблизительно оценить нагрузки и не может предсказать поведение системы в тех или иных условиях, он — плохой программист. Такая вот простая, но одновременно очень доступная мораль.
            • 0
              Парсер Excel-файла на 40000 строк и примерно 15 столбцов может сожрать до полугигабайта в оперативке.
              • 0
                Плохой парсер! Фу!
              • 0
                Предвещая претензии и аргументы — а чем не устраивает CSV?
          • 0
            Не важно хранится или нет. Вызов функции — сравнительно долгая операция в ПХП.
        • 0
          «Но по стилю её решения сразу видно какой реальный опыт имеется у человека за плечами».

          В том то и дело. Получив опыт в highload-проектах, я стал сделить за памятью в скриптах.
      • +1
        $source = array( 50 , 40 , 30 , 20, 10 );
        $rev = array();
        while ( count ( $source ) ) $rev[] = array_pop( $source );
        
        • 0
          Это вы сейчас мой пример сократили до трёх строк, да?
      • 0
        вот только php вроде как оптимизирует использование памяти при присовении значения одной переменной другой, не проверял с массивами. На хабре статья была.
      • 0
        Во второй строке ошибка.
    • –2
      Три count в цикле — не есть гуд.
      • 0
        Частично согласен, но не могли бы вы пояснить, чем именно, к примеру 3 count — не гуд, а 3 арифметические операции — гуд?

        Это я к тому, что не совсем понятно, почему вы заострили внимание именно на count, а не на арифметику с `-1`, которую точно так же можно убрать выше.
        • 0
          Я не говорил, что арифметика — гуд. Count в глаза бросился, да и все.
          • 0
            Я плохо разбираюсь в компиляторах, а в интерпретаторах и подавно, но разве count не оптимизируется во всех языках, которые только существуют? Или хотя бы в тех, о которых можно говорить в приличном обществе?
            • +1
              <?php
              
              $iterations = 100001;
              
              $arr = array('h', 'e', 'l', 'l', 'o');
              $t1 = microtime(true);
              for ($i = 0; $i < $iterations; $i++) {
              	$arr = reverse1($arr);
              }
              $t1 = microtime(true) - $t1;
              var_dump($arr);
              var_dump($t1);
              
              $arr = array('h', 'e', 'l', 'l', 'o');
              $t2 = microtime(true);
              for ($i = 0; $i < $iterations; $i++) {
              	$arr = reverse2($arr);
              }
              $t2 = microtime(true) - $t2;
              
              var_dump($arr);
              var_dump($t2);
              
              function reverse1($arr) {
              	for ($i = 0; $i < floor(count($arr)/2); $i++)
              	{
              		$tmp = $arr[$i];
              		$arr[$i] = $arr[count($arr)-$i-1];
              		$arr[count($arr)-$i-1] = $tmp;
              	}
              	return $arr;
              }
              
              function reverse2($arr) {
              	$c = count($arr);
              	for ($i = 0; $i < floor($c/2); $i++)
              	{
              		$tmp = $arr[$i];
              		$arr[$i] = $arr[$c-$i-1];
              		$arr[$c-$i-1] = $tmp;
              	}
              	return $arr;
              }
              


              Вывод:
              array
                0 => string 'o' (length=1)
                1 => string 'l' (length=1)
                2 => string 'l' (length=1)
                3 => string 'e' (length=1)
                4 => string 'h' (length=1)
              
              float 2.8682391643524
              
              array
                0 => string 'o' (length=1)
                1 => string 'l' (length=1)
                2 => string 'l' (length=1)
                3 => string 'e' (length=1)
                4 => string 'h' (length=1)
              
              float 1.7087500095367
              
              
              • 0
                Ок, понял. Для полноты картины, можете сделать тест, который в теле цикла не изменяет массив?
                • +1
                  Пустой цикл? Или как?
                  • 0
                    Пустой может как-то иначе соптимизироваться, что-то внутрь надо поместить, хоть арифметику простую. Смысл в том, чтобы сам массив не изменялся.
                    • 0
                      Вас это интересовало?

                      <?php
                      
                      $iterations = 100001;
                      $t1 = microtime(true);
                      for ($i = 0; $i < $iterations; $i++) {
                      	$a = 1;
                      }
                      $t1 = microtime(true) - $t1;
                      var_dump($t1);
                      

                      float 0.038902044296265
                      
                      • +1
                        Не-не-не :)

                        Меня интересует сравнение

                        for ($i = 0; $i < $count($arr); $i++) {
                        $a = $arr[$i];
                        }


                        и

                        $iterations = count($arr);
                        for ($i = 0; $i < $iterations; $i++) {
                        $a = $arr[$i];
                        }


                        PS: я не PHPшник, возможны ошибки :)
                        • 0
                          <?php
                          
                          $array = range(0, 100000);
                          
                          $t1 = microtime(true);
                          for ($i = 0; $i < count($array); $i++) {
                          	$a = $array[$i];
                          }
                          $t1 = microtime(true) - $t1;
                          var_dump($t1);
                          
                          $t1 = microtime(true);
                          $c = count($array);
                          for ($i = 0; $i < $c; $i++) {
                          	$a = $array[$i];
                          }
                          $t1 = microtime(true) - $t1;
                          var_dump($t1);
                          

                          float 0.24822592735291
                          
                          float 0.046469926834106
                          
                          • +1
                            Понял, спасибо. Хотя, конечно, странно, всегда считал, что такие вещи должны автоматом оптимизироваться.
                            • 0
                              каким образом интерпретатор бы оптимизировал такую вещь?
                              • 0
                                Повторю, я очень мало знаю о PHP, но мне кажется, что используется не обычная построчная интерпретация.
        • +6
          а давайте просто достанем и померяемся

          тестирующий, не побоюсь этого слова, фреймворк (PHP 5.4.0 with Xdebug v2.2.0rc1):
          $arr = range(0, 100500);
          $start = xdebug_time_index();
          // code...
          echo xdebug_time_index() - $start . ' ' . memory_get_peak_usage();
          


          результаты:
          for ($i = 0; $i < floor(count($arr)/2); $i++)
          {
              $tmp = $arr[$i];
              $arr[$i] = $arr[count($arr)-$i-1];
              $arr[count($arr)-$i-1] = $tmp;
          }
          

          0.63774108886719 8691144

          $rev = array();
          while ( count( $arr ) ) $rev[] = array_pop( $arr );
          

          0.60788989067078 9214832

          $count = count($arr);
          for ($i = 0; $i < floor($count/2); $i++)
          {
              $tmp = $arr[$i];
              $arr[$i] = $arr[$count-$i-1];
              $arr[$count-$i-1] = $tmp;
          }
          

          0.19419097900391 8691048

          $count = count($arr);
          for ($i = intval($count / 2) - 1; $i >= 0; $i--)
          {
              $tmp = $arr[$i];
              $arr[$i] = $arr[$count-$i-1];
              $arr[$count-$i-1] = $tmp;
          }
          

          0.041511058807373 8691048

          $pieces = count($arr)-1;
          $reversed = array();
          while($pieces >= 0) {
              $reversed[] = $arr[$pieces--];
          }
          

          0.039575099945068 14038952

          for ($l = 0, $r = count($arr) - 1; $l < $r; ++$l, --$r)
          {
              $t = $arr[$l]; $arr[$l] = $arr[$r]; $arr[$r] = $t;
          }
          

          0.03570294380188 8690680

          $arr = array_reverse($arr);
          

          0.014595031738281 14038056
          • 0
            Из нестандартных (array_reverse) мой вариант занял почётое второе место. Я, честно сказать, польщён, ибо код писался «на коленке» и без всяких мыслей о «померяться».
      • +1
        count не считает, он просматривает специальную переменную (или вызывает функцию, если это итератор). По сути, он быстрый.
        • 0
          Этого я не знал. Но это не отменяет факта, что count в теле цикла замедляет процесс.
    • +3
      $arr = array(‘h’, ‘e’, ‘l’, ‘l’, ‘o’);
      $arr = explode( ''@some_uniq_symbol@'', strrev( implode('@some_uniq_symbol@', $arr) ) );
      Я не использовал функцию array_reverse =)
      • +4
        $arr = array(‘h’, ‘e’, ‘l’, ‘l’, ‘o’); //init
        $arr = array(‘o’, ‘l’, ‘l’, ‘e’, ‘h’); //reversed

        :)
      • 0
        этапять :)))))
  • +3
    Не знаю, лично для меня после прочтения этой книги многое разложилось по полочкам. На собеседовании человек всегда может немного растеряться, а освежить некоторые знания всегда полезно.
    • +3
      А Вас не пугает, что там некоторая информация устарела, а некоторая была изначально неверной?
      • 0
        я читал только то, что мне было интересно и немного не понятно. Всё читать конечно бессмысленно.
        • +3
          Вы не ответили на мой вопрос.

          Вот Вы, насколько я понял, не считаете себя профессионалом в PHP, как вы определите, что в этой книжке верно и правильно? А там есть такие моменты.
          • +1
            Мы ведь все думаем, что человек должен не просто прочитать список вопрос-ответ, но и осознать прочтенную информацию?

            Даже человек который учит PHP, даже если для себя. Видимо в книге есть сомнительные куски кода и даже ошибки, однако грамотный читатель должен проверять неочевидные для себя моменты на практике.
            • +1
              Т.е. то, что в «книге» есть косяки — это нормально. А тот кто каждый пункт не перепроверил, тот сам дурак?
              • 0
                Да нет, абсолютно не правильный вывод.

                Просто это не энциклопедия. Я, например, сейчас изучаю «Cambridge grammar for First Certificate» — кажется, что Кэмбриджу можно доверять полностью, в отличие от Андрея Шевченко, однако, я всегда дополнительно изучаю неочевидные для меня вещи. Или случаи, когда употребление каких-то конструкций для меня просто подозрительно.

                Смысл прочтения без осознания прочитанного = 0.
                • 0
                  Не путайте. Осознание != проверка каждого высказывания. Неочевидное != ошибочное.
              • 0
                Ну не знаю. Если бы в инструкции к револьверу было что-нибудь про «выстрелить себе в ногу для проверки на холостые» я бы задумался =)
                • 0
                  Потому что, у вас есть теоретическое знание о револьверах, которого достаточно, чтобы представить, что может произойти, если патрон окажется боевым.

                  А вот если бы вы не знали, вы бы могли и последовать инструкции. Речь об этом. Просто знание про револьвер более распространённое и более наглядное, проще представить, а знание про ЯП — менее распространённое, менее наглядное, и сложнее обнаружить инструкции, аналогичные выстрелам в ногу для проверки холостых.
                  • 0
                    Склоняюсь перед Вашей волей.
                    Просто я уже десяток лет изучаю стили и языки программирования, и каждый «мануал» по привычке вызывает у меня долю недоверия и желание проверить всё на практике.
                    Von lict Jovi, non licet bovi — Что очевидно профессионалу совершенно не очевидно новичку. Немножко не точно, зато в тему.
          • 0
            Конечно я не профессиональный PHP-программист! Я там себя не буду считать никогда, потому что нет предела совершенству! Т.к. большую часть своей короткой жизни я изучал C#, то некоторые моменты мне были яснее некуда, но некоторые моменты стоили того, чтобы их прочесть и осознать. Если для меня что-то покажется не таким, каким я это видел до этого, я спрошу на работе, правильно ли это или нет.
            • 0
              А, если не покажется? Но это будет тем не менее неправильным, а Вы запомните так как есть?
              • 0
                Т.к. я всё-таки ещё учусь, то подвергаю сомнению всё, что не соотносилось с моей деятельностью на C#
                • –1
                  Эта «книга» подходит для теста типа «найдите, что здесь не так», а не для обучения.
                  • +1
                    Никто и не спорит. Но это не меняет факта, что там есть вещи, которые могут знать не все. И я говорю не только о примерах кода, но и собственно ответах на вопросы.
                    • 0
                      А кто не даёт Вам читать мануал? Там явно больше вещей, которые могут знать не все.

                      Насколько хорошо Вы знаете английский?
                      • 0
                        На уровне того, что преподавали в институте
                        • 0
                          Узнайте тогда что такое ZCE и найдите соответствующую книгу. Это будет гораздо полезнее.
                          • 0
                            Ничего ответить на такое не могу
      • 0
        Какая конкретно информация устарела?
  • +1
    Подходит только при собеседовании на вакансию начинающего кодера, проверяются только базовые вещи и уровень владения мануалом.
    • 0
      именно на начинающий уровень и рассчитано.
  • 0
    Если честно хрень какая-то, у меня спрашивали паттерны, оптимизация под highload, системы контроля версий, phpDoc ну и еще что-то, уже не помню
    • 0
      на собеседовании на джуниора?
      • 0
        Угу.
  • +1
    33. Используя конструкцию switch, написать функцию boo, принимающую
    одно число в качестве аргумента. Если это число равно 2, функция должна
    вывести слово “Двойка”, если 3 – “Тройка”, в остальных случаях – “Фигня ка-
    кая-то”.
    <?php
    function boo($num) {
    switch($num) {
    case “2”:
    echo “two!”;
    break;
    case “3”:
    echo “three!”;
    break;
    default:
    echo “shnyaga!”;
    break;
    }
    }
    boo(2);
    ?>


    Тваюжмать :((
    • 0
      Я всегда буду пользоваться предпросмотром
      Я всегда буду пользоваться предпросмотром
      Я всегда буду пользоваться предпросмотром
      • +3
        … и тегом <source>
    • 0
      что не так?
      • 0
        > «Фигня какая-то»
        > echo “shnyaga!”;

        Если вы называете этот документ «книгой», думаю, данные выражения не слишком в ней уместны.
        • 0
          А что, на собеседованиях говорят «Извольте, господин»? Или все же «шняга»?
  • +3
    Отличная штука. :) Пусть как можно больше чуваков её вызубрят, можно будет легко таких отсеивать на собеседованиях. Например, в вопросе #22, где используется strlen(), можно тестируемому подсунуть кириллическую строку в UTF-8 и посмотреть, как он удивится, когда заученный пример отработает некорректно. :)

    Приходилось собеседовать довольно много разработчиков, и основываясь на своём опыте могу сказать, что хороших рарзработчиков удавалось найти и без таких вопросов. :)
    • +1
      Попадался мне такой супер герой шутник с кириллицей на собеседовании. Сидит улыбается, ждет, что я буду делать. Я ему говорю, у Вас тут iconv не хватает, лучше заменить на mb_strlen.

      И о чудо! Он мне говорит — «Неправильно! Нужно использовать другую кодировку!»

      • +1
        У Вас «супергерой шутник» в какой–то негативной коннотации приведено. :)

        Так или иначе, если собеседование предполагает тестирование на месте, у меня есть простой тест на знание PHP и MySQL, через который я сам когда–то проходил при приёме на работу разработчиком. Тест простейший (делается за 10–15 минут), но за последние 5 лет его использования не дал ни одной осечки: на прошлом месте работы все разработчики, которые его выполняли, были приняты на работу и отлично себя проявляли.

        Но в последнее время уже и тестов не требуется, как правило: достаточно послушать, как и что человек рассказывает о задачах, которые ему приходилось решать, и можно, в общем–то, получить достаточное представление о его квалификации и вменяемости.
  • +5
    Существует ли универсальная защита от SQL-инъекций?
    Про Prepared statements ни слова, зато есть strip_tags. О_о.
    • +3
      Вы что не знали что это универсальная защита? Нет тэгов нет иньекций!
    • 0
      ВСЁ перечислять совершенно не обязательно. Книга рассчитана на уровень начинающего.
  • +1
    Сейчас автор начитается комментов и выпустит второе издание)
    • 0
      таки да! я уже записываю критику :)
  • +22
    Вывести только те магазины, которые находятся во Львове и/или Харькове:
    SELECT * FROM shops WHERE area=”Львов” AND area=”Харьков”

    Это гениально! Ничего, что результат будет 0 строк по определению? Вообще на этапе разбора запроса? =)
    • +18
      > находятся во Львове и/или Харькове

      В соответствии с бизнес-требованиями следовало запрос написать соответственно:

      WHERE area=”Львов” AND/OR area=”Харьков”
      • +3
        AND тут вообще не катит. Не может быть одно поле быть одновременно и «Львов» и «Харьков»
        Это просто разрыв шаблона какой-то.
        • +2
          С бизнес требованиями все нормально, в них ничего нет про одно поле.
        • 0
          не может. ошибка :( бывает…
    • 0
      поправим :)
      • +2
        Ещё уберите rand и используйте mt_rand.
        • 0
          откуда убрать? зачем?
          • +1
            Из кода. Это плохой генератор.
  • +2
    На моем недавнем собеседовании работодатель был явно под влиянием этой книги.
    • 0
      половина работодателей такие :)
  • 0
    Местами немного устарело, но в целом очень и очень неплохо.
    Хотя бы, нет вроде, идиотских вопросов: «что выведет на экран $i++ -$i-- * ++$j» и всякого такого

    А вообще по-моему, для первоначального отсева лучше небольшое тестовое задание.
    Все равно нет гарантий, что человек будет практически полезен в данной конкретной организации в конкретном коллективе в конкретных проектах.
    • –1
      вопрос типа «чему равно $i после выражения $i+= $i++ + ++$i» — очень неплохой. на относительно простом примере можно увидеть понимание основ и финтов ушами. и если человек вообще не может ответить, то дальше можно ничего не спрашивать.
      • +1
        А где описано, над чем оперирует унарный оператор `++`, над значением или над ссылкой?

        Если вы считаете, что пример хороший, не могли бы вы указать на место, где это поведение определяется в явном виде?
        • +1
          Точнее, пардон, неправильно сформулировал — что должно возвращаться после унарной операции в выражение — значение или ссылка?
        • +3
          видите ли, ваш ответ уже неплох, так как вы увидели проблему в неполных начальных условиях.
          а если написать кандидату

          $i = 5;
          $i+= $i++ + ++$i;


          а он сразу зависает, потому что в «книге» из топика такое не описывалось — вердикт очевиден.
          • +4
            Ну я просто как бы уже не джуниор давно, гхм.

            А вопрос всё равно плохой. С новичком можно обсудить тему для новичков, с неновичком — можно обсудить темы для неновичков. А этот вопрос лучше не обсуждать ни с кем :-)
      • +2
        Пример из маунала:
        // mixing ++ and + produces undefined behavior
        $a = 1;
        echo ++$a + $a++; // may print 4 or 5

        Каких таких основ и финтов?)
        • +1
          Проверка навыка «умение разбираться в чужом коде» в действии же :-)
          • 0
            наличие навыка гадания в чужом коде, скорее ;)
          • 0
            конечно же, все устраиваются на работы, где нету ни строки legacy-кода, где есть полная и актуальная документация, где не приходится переписывать какие-то устаревшие куски кода, где не приходится допиливать какую-то мелкую фичу. да, если кругом только такие работы, то умение разбираться в чужом коде — лишнее. в противном случае это весьма полезный скилл.
            • 0
              Это шутка ведь была :-)

              Я согласен, что это полезный и очень крутой навык (тут уже не ирония, недавно видел как человек в огромном и новом для него проекте за считанные секунды нашёл нужный код).
      • +1
        Единственным верным ответом на него, имхо, может быть только следующее: я никогда так не напишу, а если встречу в чужом коде, то трогать не буду пока работает. И только в случае реальной надобности тронуть, аккуратно разберусь.

        В жизни не поверю что серьезный разработчик каждый день пишет или видит подобные извраты и, соответственно, помнит все тонкости языка. Не, если нужен именно code monkey, знающий только один язык и учивший мануал, вместо получения опыта реально работы, тогда другой разговор.
    • +11
      что выведет на экран $i++ -$i-- * ++$j

      Оно выведет из себя программиста, поддерживающего этот говнокод.
    • 0
      а что именно устарело?
      • 0
        Многие вещи, которые я считаю устаревшими или спорными, тут уже, в принципе, описали. А многое слишком субъективно и очень спорно, не хотелось бы разводить флейм. Наверное, я лучше как соберусь и оформлю свои мысли, пришлю вам в личку, если вы, конечно, не против. В целом все очень хорошо, я даже знаю одного человека, который уже проводил собеседование по вашим вопросам :)
  • 0
    Может всем хабросообществом напишем книгу?)
    • +7
      Логичнее будет помочь с переводом документации на php.net
      • +1
        Пожалуй с вами я согласен
  • +3
    39. Есть массив a = array(тут много элементов). Проходим по массиву циклом for (i=0; i<=count(a); i++). Можно ли как-нибудь ускорить цикл?
    Да.
    1) Вынести count(a) в отдельную переменную;
    2) Считать массив с конца циклом for (i=count(a); i>=0; i--).

    foreach уже запретили?
    • +1
      Очень показательно, что второе решение в принципе рассматривается решением. Другими словами — код, по идее автора книги, предназначен не для того, чтобы решать конкретную задачу (для которой, почти наверняка, обход в обратном порядке неприемлем или приведёт к переписыванию тела цикла), а просто для того, чтобы радовать глаз
      • 0
        Это собеседование, поэтому тут не конкретные задачи решаются, а проверяется понимание того как работает цикл (в данном случае) и можно ли его в принципе написать иначе как (i=0; i<=count(a); i++). Напомню, что собеседование на джуниора.
        • 0
          Тем более. Не нужно пудрить джуниору мозг, а то он прочитает вашу книгу и поверит, что обход с последнего элемента массива происходит быстрее.

          Хотите узнать про принципы — спросите в явном виде, как обойти массив с конца, не притягивайте за уши всякую фигню.
          • 0
            Это вопрос РЕАЛЬНОГО собеседования и ответ про обход массива с последнего элемента — РЕАЛЬНЫЙ ответ собеседующего в качестве правильного ответа :) А книга основана на РЕАЛЬНЫХ вопросах и ответах, сколь бы дурацкими они не были.
            • 0
              Даже если это реальный вопрос, то НЕЛЬЗЯ отвечать на него подобным образом. Просто потому что у вас нет тела цикла.

              > в качестве правильного ответа
              Ну значит и собеседующий, и собеседуемый друг друга стоят. Ибо НЕЛЬЗЯ такой ответ принимать правильным.

              Программисты решают реальные задачи, а философией занимаются философы.

              Более того, вариант 2 является частным случаем варианта 1. Какой смысл говорить о том, о чём уже сказали?
    • 0
      И причем здесь foreach, если вопрос «Можно ли как-нибудь ускорить цикл for»?
      • 0
        Можно сбросить еще одну итерацию, написав i < count(a), т.к. счет идет с нуля до count(a)-1.
      • +1
        притом, что это самый быстрый способ обойти массив, собственно для этого он и придуман.
        • 0
          — Как быстрее всего доехать до Киева на поезде?
          — Да зачем на поезде, на самолете же быстрее! Он же для этого и придуман!
          — Но мне нужно на поезде…
  • +1
    Мало того, что ответы на вопросы не полные и не правильные, так еще и вопросы для собеседования детские. Меня шманали по ООП, нагрузки, linux, mysql (join'ы и их отличия друг от друга и др.), варианты кеширования, JS: как быстрее ищет, по id или классу и так далее, jquery, ajax и др. Логика, быстрые и правельные решения.
    • 0
      Это было собеседование на джуниора?
  • +1
    Ух сколько критики! Но это и хорошо. Сделаем «Издание второе. Дополненное и переработанное» :)
    • 0
      Всецело одобряю задумку. Может набросать по-быстрому сайтик с вопросам-ответами для собеседований? Типа, собеседование на «пэхапэшника» и вопросы пользователей с рейтингами. Если рейтинг уходит в негатив, то вопрос скрывается. То же для всяких монтажников-админов-бухгалтеров. По-моему, удобно!
      • 0
        хорошая идея
    • 0
      На фоне Вашей книги, у многих появилась возможность блестнуть умом :)

      Во втором издании код отформатируйте, пожалуйста, а еще лучше — подсветите.
    • +1
      Приходилось ли Вам проводить собеседования?
      • –1
        нет
        • +4
          И Вы автор этой книги?
          • 0
            похоже на то :)
            • +6
              Этого я и боялся.: )
              • 0
                Да бояться не стоит :)
        • +2
          И сколько собеседований Вы прошли? :)
          • –2
            много)
            • +3
              Успешно?
              • –3
                когда как :)
            • +6
              это печально
    • 0
      Числа Фибоначчи нельзя получать при помощи рекурсии. Я всегда считал, что именно в этом подвох.
      В любом случае, сборник очень даже хорош. Спасибо!
      Когда ждать второе издание? Будете ли писать где-нибудь в github? Можно поучаствовать?
      • 0
        Естественно :) Становитесь соавтором.
        • 0
          Где происходит написание? Можно линк на гитхаб (или куда то-ещё)?
          • 0
            У меня еще нет аккаунта на гитхабе. Я сперва переделаю книгу с учетом озвученной здесь критики :)
            • 0
              Ну, в общем, как Вам будет удобнее. В гитхаб (или bitbucket-закрытые бесплатные репозитории) в формате markdown можно писать, он удобный, а перед выходом переводить в PDF. Многие книги так и писались, о них тут (на хабре) писалось.
              Либо просто могу дописывать свои вопросы и присылать по старинке по электронной почте.
              • 0
                а пока можно прислать по почте или скайпу свои вопросы :) я пока буду импрувить то, что есть :)
            • 0
              И вообще, предлагаю в конце сделать приложение — примеры реальных тестовых заданий из реальных фирм. У меня скопилось немного.
              • 0
                насчет приложения — отличная идея. давайте сделаем.
      • 0
        Это почему нельзя?
        • 0
          Сложность алгоритма примерно C^n.
          Например, для вычисления всего лишь 5000-го числа фибоначчи нужно выполнить 3,9803*10^1020 операций.
          Тысяча нулей — это очень, очень, очень много.
          • 0
            Насколько я понимаю, для вычисления 5000-го числа Фибоначчи требуется всего 5000 операция сложения — выполнится быстро (у меня получилось 0.012 с.). Проблема в том, что результат получится очень большой и не влезет в стандартные числовые типы данных.
            • 0
              проблема не в числовых типах данных, а в stack overflow -)
              • 0
                В моём случае как раз в типе данных. При генерации 50 миллионов чисел у меня таки вылезла ошибка java.lang.OutOfMemoryError: Java heap space, но я подозреваю, что при необходимости это можно подкрутить в jvm.
            • 0
              Неверно. Я взял рекурсивный код из книги и добавил счётчик. Вот, что вышло.
              <?php
              $counter=0;
              function fibonacci($n)
              {
              	global $counter;
              	$counter++;
              	if ($n < 3) {
              		return 1; 
              	} else {
              		return  fibonacci($n-1) + fibonacci($n-2);
              	}
              }
              for ($n = 1; $n <= 40; $n++) {
              	$counter=0;
              	echo(fibonacci($n) . "  ");
              	print " Операций: ".$counter.'
              ';
              }
              
              

              Вот вывод строк 27, 28, 29, 30, 31
              196418 Операций: 392835
              317811 Операций: 635621
              514229 Операций: 1028457
              832040 Операций: 1664079
              1346269 Операций: 2692537
              

              После этого прошло 30 секунд и скрипт умер. 32-е число найдено не было.
              Попытка найти 40-е число Фибоначчи без лимита по времени приводит к долгим размышлениям. На самом деле, до сих пор думает. Находить 5000-е не буду.
              Таким образом, пример из книги просто-напросто неспособен найти 100-е число, к примеру.
              • 0
                Додумалось
                102334155 Операций: 204668309
                Для 40-го числа это очень, очень много.
              • 0
                Ого. Книгу я не смотрел, на самом деле. Просто на Ваш комментарий обратил внимание и не подумал, что он к конкретному примеру из книги относится. :)
                • 0
                  Вчитался в код… Да, так бы я не додумался написать.
            • 0
              5000 операций сложения — это как раз правильный подход. А в книге — не совсем правильный пример. Вернее, совсем неправильный.
  • +2
    Ответы на вопросы по собеседованию PHP

    5. В чем различие между PHP4 и PHP5

    Автор не назвал самого главного — _несовместимых_ изменений. По крайней мере одно (и самое главное, ИМХО) я могу назвать — теперь объекты представляют из себя не _значение_, а ссылку на значение, где значением выступает экземпляр объекта. Присваивание $b = $a больше не делает полной копии объекта, а копируется лишь ссылка на него.

    7. О типизации данных в PHP

    Интересно привести пример, когда эта динамическая типизация вредит:

    следите за руками
    $a = 0;
    $b = null;
    $c = «0»;
    и вот, что получается:
    $a == $b, $a == $c, $a != $b

    Вот, что я могу сказать о динамической типизации в пхп :).

    8. Сколько типов данных в пхп:

    Правильный ответ: хз, но у int (integer) в 32-х и 64-х битных версиях разные диапазоны макс. значений, что играет роль в работе, к примеру, функции filesize, которые возвращают «int» (в самом коде PHP используется long, чтобы хранить «int»).

    11. Что такое конструктор (класса)

    В PHP4, если метод класса называется также, как и сам класс, то он вызывается перед тем, как new вернет инстанс соответствующего объекта. То же самое работает и в PHP5 из соображений обратной совместимости, но при этом было выбрано более удобное название — __construct, а также введены __destruct, __clone и т.д.

    21. Как перевернуть массив без использования array_reverse

    Не надо этого делать из соображений эффективности работы. Если очень хочется, то можно вот так:

    for($i = count($arr) — 1; $i >= 0; $i--) $new_arr[] = $arr[$i];

    Этот код перевернет массив с сохранением строковых ключей, если они были (об этом в вопросе ничего не было сказано, значит предполагаем, что это возможно)

    22. Как перевернуть строку:

    Однобайтовая кодировка: strrev
    Многобайтовая (UTF-8):

    $tmp_str = iconv(«UTF-8», «UTF-16», $str);
    $new_str="";
    $chars = strlen($tmp_str) / 2;
    for($i=$chars-1; $i >= 0; $i--) $new_str .= $tmp_str[$i*2].$tmp_str[$i*2+1];
    $new_str=iconv(«UTF-16»,«UTF-8»,$new_str);

    Только такой вариант будет работать за O(N), вариант с простым mb_substr доя UTF-8 будет давать O(N^2), к сожалению

    Написано с телефона
    • 0
      > Только такой вариант будет работать за O(N)

      А подскажите сложность iconv() в её текущей реализации?
      • 0
        Должна быть O(N), поскольку он просто проходит строку последовательно
      • +2
        Я не смог найти информацию о производительности iconv(), поэтому решил провести бенчмарк предложенной ниже реализации strrev (в одну строчку):
        <?php
        $strings = array();
        for ($i = 1; $i <= 100; $i++) {
        	$strings[] = str_repeat('а', 1000 * $i);
        }
        
        foreach ($strings as $str) {
        	$start = microtime(true);
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
        	echo ((microtime(true) - $start) * 1000) . "\n";
        }
        


        График времени от номера итерации вот такой:


        По мне так чистый O(N)
        • 0
          Реализация с mb_substr, чтобы не было вопросов:

          <?php
          $strings = array();
          for ($i = 1; $i <= 100; $i++) {
          	$strings[] = str_repeat('а', 100 * $i);
          }
          
          mb_internal_encoding("UTF-8");
          function mb_strrev($str) {
          	$len = mb_strlen($str);
          	$new_str = '';
          	for ($i = $len - 1; $i >= 0; $i--) $new_str .= mb_substr($str, $i, 1);
          	return $new_str;
          }
          
          foreach ($strings as $str) {
          	$start = microtime(true);
          	mb_strrev($str);
          	echo ((microtime(true) - $start) * 1000) . "\n";
          }
          


          Надеюсь, все юзают этот график:
          • 0
            «Надеюсь, все узнают этот график»
            • 0
              Я делал отдельные бенчмарки по производительности оператора ".=" в PHP, можете мне поверить на слово, время работы ".=" в PHP — это O(1), а значит время работы цикла с ".=", в результате которого получается длина строки N, составляет (грубо) O(N). Поэтому проблема именно в mb_substr(), что не должно удивлять, если подумать над тем, как реализовать substr для строки с переменной длиной одного символа, кроме как пройтись по всей строке с самого начала.
          • 0
            И теперь ещё реализация от Joomla (за время, близкое к O(1), но намнооого медленней):

            <?php
            $str = str_repeat('а', 99) . 'б';
            
            mb_internal_encoding("UTF-8");
            function utf8_strrev_joomla($str){
                preg_match_all('/./us', $str, $ar);
                return join('',array_reverse($ar[0]));
            }
            
            function utf8_strrev_mb($str) {
            	$len = mb_strlen($str);
                $new_str = '';
                for ($i = $len - 1; $i >= 0; $i--) $new_str .= mb_substr($str, $i, 1);
                return $new_str;
            }
            
            function utf8_strrev($str) {
            	return iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
            }
            
            $start = microtime(true);
            for ($i = 0; $i <= 10000; $i++) {
            	utf8_strrev_joomla($str);
            }
            echo "Joomla: " . round(microtime(true) - $start, 5) . " sec\n";
            
            $start = microtime(true);
            for ($i = 0; $i <= 10000; $i++) {
            	utf8_strrev_mb($str);
            }
            echo "Mb:     " . round(microtime(true) - $start, 5) . " sec\n";
            
            $start = microtime(true);
            for ($i = 0; $i <= 10000; $i++) {
            	utf8_strrev($str);
            }
            echo "My:     " . round(microtime(true) - $start, 5) . " sec\n";
            
            $start = microtime(true);
            for ($i = 0; $i <= 10000; $i++) {
            	strrev($str);
            }
            echo "Plain:  " . round(microtime(true) - $start, 5) . " sec\n";
            
            $ref = utf8_strrev_joomla($str);
            
            if ($ref != utf8_strrev_mb($str)) echo "Mb is incorrect\n";
            if ($ref != utf8_strrev($str)) echo "My is incorrect\n";
            if ($ref != strrev($str)) echo "Plain is incorrect\n";
            


            Длина строки 10 символов:
            Joomla: 0.06649 sec
            Mb:     0.05858 sec
            My:     0.02206 sec
            Plain:  0.00231 sec
            Plain is incorrect
            


            Длина строки 100 символов:
            Joomla: 0.5095 sec
            Mb:     0.67563 sec
            My:     0.04836 sec
            Plain:  0.00398 sec
            Plain is incorrect
            


            Вывод: используйте мою реализацию для UTF-8, как самую быструю, но если вам не надо UTF-8, то используйте strrev, оно ещё в 10 раз быстрее. Ну и не используйте реализацию через mbstring на больших строках (на 1000 байт разница становится очень ощутимой) — график я привел выше.
            • 0
              Моя исходная реализация (через ".=") обладает сложностью O(1), но работает за такое же время, как и вариант с Joomla (кстати, та же реализация используется почти везде, где я видел в гугле).
            • 0
              Ещё быстрее на моём итераторе для UTF-8: http://bolknote.ru/2012/04/02/~3625#n34383
            • 0
              Вы не совсем честно оцениваете работу через mbstring. Следующая реализация на mbstring дает примерно такой же результат по времени что и реализация через iconv.
              function utf8_strrev_mb2($str) {
                  return mb_convert_encoding( strrev( mb_convert_encoding($str, 'UTF-16BE', 'UTF-8') ), 'UTF-8', 'UTF-16LE');
              }

              А аналогичный вашему варианту mbstring код на iconv у меня выполняется в 10 раз дольше.
              function utf8_strrev_iconv2($str) {
                  $len = iconv_strlen($str, "UTF-8");
                  $new_str = '';
                  for ($i = $len - 1; $i >= 0; $i--) $new_str .= iconv_substr($str, $i, 1, "UTF-8");
                  return $new_str;
              }
              • 0
                Да, имелось ввиду «очевидное» решение в виде mb_substr, я согласен, можно использовать либо только расширение mbstring, либо только iconv в данном случае — это не принципиально.
    • +1
      Сорри, про строковые ключи забыл удалить — в исходном примере был приведен обычный массив
    • 0
      <?
      $test = 'Тест';
      
      $end  = strlen($test)-1;
      $half = strlen($test)>>1;
      
      $test = iconv('utf-8', 'utf-16le', $test);
      
      for ($i = 0; $i < $half; $i++) {
          list($test[$i], $test[$end-$i]) = array($test[$end-$i], $test[$i]);
      }
      
      echo iconv('utf-16be', 'utf-8', $test);
      
      • 0
        Ну кстати, есл использовать этот трюк, то и strrev подойдет :)
        • 0
          Я понял задачу как «strrev» недоступен.
          • 0
            Вроде как заголовок был «Как перевернуть строку», про strrev я ничего не говорил :)
      • 0
        То есть:
        function utf8_strrev($str) {
        return iconv("UTF-16LE", "UTF-8", sttrev(iconv("UTF-8", "UTF-16BE", $str)));
        }
        
        • 0
          Тут есть опечатка, если что, правильная функция вот (sttrev -> strrev):
          function utf8_strrev($str) {
              return iconv("UTF-16LE", "UTF-8", strrev(iconv("UTF-8", "UTF-16BE", $str)));
          }
          
    • –1
      Хм,

      $a = 0;
      $b = null;
      $c = "0";
      
      echo ($a == $b);
      echo ($a == $c);
      echo ($a == $b);
      


      Результат: 111
      Или я вас неправильно понял?
      • 0
        Прошу прощения, с телефона писал, в последнем примере, конечно же, $b != $c, иначе получается повторение первого условия
    • 0
      По поводу 7:

      $a == $b //TRUE if $a is equal to $b after type juggling
      Читаем мануал.

      Поэтому пример о типизации невалидный.
      • 0
        Я не понял, в чём проблема с примером (кроме того, что я повторяю $a == $c два раза вместо того, чтобы в конце сравнивать $b и $c)?
        • 0
          Ну вот комментарий: >> Интересно привести пример, когда эта динамическая типизация вредит
          Далее используется оператор сравнения "==" вместо "==="

          В мануале четко скзано: оператор "==" сравнивает значения ПОСЛЕ приведения типа.
          Т.е в вашем примере интерпретатор поступает четко по правилам.

          Т.е если считать что ето «вредное поведение», то по той же логике можно считать вредным и например такое поведение:

          $i = 3;

          if ($i > 2 || exit()) {
          echo 'hello';
          }


          // Выведет hello

          В чем схожесть этих двух примеров? В том что программист сознательно отстреливает себе ногу, но возмущается тому что ему разрешают это делать.
          • 0
            Я лишь говорю о том, что благодаря слабой динамической типизации в PHP, как и в Perl, нельзя писать, к примеру, следующее для проверки строки на пустоту:
            $str = "0";
            if ($str) echo 'EMPTY';
            else echo 'NOT EMPTY';
            
            if (empty($str)) echo 'EMPTY';
            else echo 'NOT EMPTY';
            


            А нужно писать, к примеру, так:
            if (strlen($str)) echo 'EMPTY';
            else echo 'NOT EMPTY';
            


            Я считаю, что эта тема важна (по крайней мере, я писал СУБД на PHP, и такие «тонкости» были весьма неприятны), и, по-моему, есть и другие примеры, где приведение типов в PHP приводит к тому, что a == b, b == c, но a != c, и не надо мне рассказывать про оператор тройного равенства — он нужен только при сравнении, когда вам заранее известен тип, а в остальных случаях, как мне кажется, его использование вредно, поскольку, к примеру, любой встроенной функции в PHP спокойно можно передать строку вместо числа и она будет нормально сконвертирована в число, а если вы будете внутри функции на PHP проверять числа на тройное равенство, то вы упустите такой момент и ваша функция будет просто работать нестандартно и, скорее всего, просто неправильно.
            • 0
              Прошу прощения, правильный код:
              $str = "0";
              if (!$str) echo 'EMPTY';
              else echo 'NOT EMPTY';
              
              if (empty($str)) echo 'EMPTY';
              else echo 'NOT EMPTY';
              
              if (!strlen($str)) echo 'EMPTY';
              else echo 'NOT EMPTY';
              


              Очень жаль, что я не могу сразу отредактировать свой комментарий, чтобы поправить ошибки :)
            • 0
              я понял мысль, но c empty() должно работать
              • 0
                Мало ли, что оно там должно, я вам говорю о том, как оно на самом деле работает. В PHP есть много интересных моментов, и если вы с ним работаете 8 лет, то вы их будете находить (как и в любом другом языке, естественно :))

                $ cat test.php
                <?php
                $str = '0';
                if (empty($str)) echo "Empty\n";
                else echo "Not empty!\n";
                $ php test.php
                Empty
                
                • 0
                  Я наверно не понял примера :) Но ваш скрипт работает так как я ожидал :D
                  • 0
                    Ну, строка, в которой записано «0», очевидно, не пустая, а empty() возвращает при этом true, что некорректно. А работает-то оно в любом случае, вопрос только в том, корректен ли результат :))
    • 0
      >> $a == $b, $a == $c, $a != $b

      неверно.

      $a == $b, а вот $b != $c :)
  • 0
    Я даже кандидатам в джуниоры не задаю вопросов вроде echo vs print и т.п. Предвижу в ближайшее время наплыв выпускников славной академии Шаг и прочих компьютерных колледжей, почитавших сей славный мануал, и желающих $1k+ (Харьков).
    • 0
      Одни задают, другие не задают. В любом случае, вопрос про echo vs print — это вопрос с реального собеседования.
  • –1
    Ни на один вопрос не ответил бы, да и не отвечу, хотя на мне куча проектов на старичке php. Как же так?
    • 0
      даже на «Как перевернуть строку?» :)
      • 0
        Дело в том, что задача переворачивания строки с реальностью не имеет ничего общего.
        • 0
          Половина тех вопросов, которые задают на собеседованиях не имеет ничего общего с реальностью :) Но их же все равно задают…
  • +3
    >Что такое динамические переменные
    Как бы все переменные

    >Назови и опиши пять любых типов ошибок PHP
    Не разбираюсь в типах ошибок php, знаю английский и в состоянии отличить notice от error, да и вообще век exceptions

    >В чем различия между четвертой и пятой версиями PHP?
    Какая разница? Если я этого не буду знать это как-то навредит мне при решении проблем? Один из глупейших вопросов собеседований. Суть то ведь в том, что какая может быть разница «какой вообще язык использовать для решения задачи» — выбор всегда падает на наиболее доступный и наиболее легкий вариант для решения текущей проблемы, да и таковых проблем может быть несколько, и для каждой свой язык.

    >Поддерживает ли РНР множественное наследование?
    traits

    >Как перевернуть строку/массив/блабла?
    Эти вопросы натянуты до нитки, потому что в реале такие проблемы встают редко, и как правило решаются гуглом (как и большинство проблем с незнанием языка), если свой перегретый мозг сделать это не в состоянии

    >ряд чисел фибоначчи
    С пе