• Истории о моей работе в Нидерландах

      Давно не писал на хабр, и вот приспичило. Истории со временем забываются, стираются из памяти, хочу записать в том виде, в каком сейчас помню.


      Я живу в Нидерландах уже почти 5 лет, и мне здесь очень нравится. Здесь у нас родился сын, мы купили дом и посадили рядом с ним дерево. Но по работе за это время случалось всякое. Вот несколько историй я и хочу рассказать.


      image

      Читать дальше →
    • Протокол Handlersocket в деталях

        Всем здрасьте. Решил опубликовать русскую версию своей же статьи «HandlerSocket protocol explained», опубликованной по адресу http://wk-photo.ru/en/events/view/handlersocket-protocol-explained/.

        image

        Итак, вы шли-шли и пришли к HandlerSocket. Чистый мёд. Это дьявольски быстрый вуду. А используемый протокол реально простой, как две копейки. Ну и если уж начистоту, кому важны детали протокола, если все равно будет использоваться какая-то библиотека, которая обо всем позаботится? Если, несмотря ни на что, вы все-таки хотите знать, что за неонка там внутре, можете нагуглить эту страницу. Несколько часов — и вы эксперт. Ну или вы хотите все и за 15 минут. Тогда добро поржаловать под кат!

        Читать дальше →
        • +6
        • 14.7k
        • 2
      • ZF2 + Blitz templates

          Здравствуйте, разлюбезные мои хабровчане. А ежели кто из вас веб-разработкой на PHP занимается, то и вообще добро пожаловать. Я тут давеча стал смотреть на разные фреймворки… Развелось их у нас в ПеХаПе — страсть. Яблоку негде упасть, как говорят блондинки.


          Читать дальше →
          • –1
          • 7.5k
          • 5
        • mod_rewrite и пользовательские переменные окружения

            Есть в сервере Apache модуль mod_env, с его помощью можно задавать пользовательские переменные окружения:

            SetEnv foo bar

            Мне нужно было использовать такую пользовательскую переменную окружения в директиве RewriteCond модуля mod_rewrite. Оказалось, однако, что переменные, заданные с помощью SetEnv — в mod_rewrite недоступны :(. Увы!

            Что же делать? Решение очень просто. С помощью вот такого нехитрого правила можно задать переменную окружения, которой mod_rewrite сможет потом воспользоваться:

            RewriteRule .* - [E=foo:bar]

            Перенаправления не происходит, мы просто задаем переменную окружения foo со значением bar (A dash indicates that no substitution should be performed (the existing path is passed through untouched) — httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriterule).

            Далее этой переменной можно воспользоваться:

            RewriteCond %{ENV:foo} bar # следующее правило будет применено только если переменная foo имеет значение bar.

            (обратите внимание на префикс ENV: насколько я понимаю, он обязателен для использования своих переменных окружения, тогда как стандартные, типа QUERY_STRING можно использовать и без него)

            Вот и все. Надеюсь, тем, кому (как и мне) нечасто приходится настраивать апач, эта информация окажется полезной
          • PHP — оптимизация многочисленных array_merge()

              Небольшой хинт, о котором я собираюсь сейчас рассказать, я узнал уже довольно давно. Но, поскольку вот только что обнаружил, что именно в этом месте оптимизация помогла сэкономить изрядное количество времени уже в текущем проекте, то решил поделиться с общественностью (а мужики-то не знают, ага).

              Буду краток, вот тестовый скрипт и то, что он выводит:

              $start = microtime(true);
              $res1 = array();
              for ($i = 0; $i < 1000; $i++) {
                      $res1 = array_merge($res1, array(1, 2, 3));
              }
              echo "1000 merges: " . ceil((microtime(true) - $start) * 1000) . "ms\n";
               
              $start = microtime(true);
              $toMerge = array();
              for ($i = 0; $i < 1000; $i++) {
                      $toMerge[] = array(1, 2, 3); 
              }
              $res2 = call_user_func_array('array_merge', $toMerge);
              echo "call_user_func_array('array_merge',..): " . ceil((microtime(true) - $start) * 1000) . "ms\n";
               
              echo "Is it true that the two arrays are equal? It is ";
              var_export($res2 === $res1);
              echo ".\n";

              ~ % php ~/tmp/array_merge.php
              1000 merges: 980ms
              call_user_func_array('array_merge',..): 11ms
              Is it true that the two arrays are equal? It is true.


              Экономия солидная. Авось кому пригодится.
            • FF — интересный момент, которого раньше не знал

                Сразу к делу.

                В форме сделал такую конструкцию для автокомплита (два инпута внутри одного label):

                label
                -> input type=hidden
                -> input type=text


                И обнаружил, что при таком раскладе текстовое поле не может получить фокус после клика мышью (курсор появляется и тут же исчезает, если начать ввод с клавиатуры — ничего не происходит). После выяснил: если оба инпута сделать текстовыми, то отчетливо видно, что делается: при клике на второй инпут (mouseDown) курсор там появляется, но при mouseUp он тут же перескакивает на первый инпут. Раньше такого не знал, да и поиск не шибко помог (может, конечно, плохо искал), вот и решил опубликовать.

                Да, кстати, если перемещаться по форме с помощью Tab — все нормально, фокус не теряется. И еще — в хроме такого эффекта нет, больше нигде не смотрел.
              • Красивые и правильные даты на любом языке

                  Прочитал топик Патч к Drupal-модулю Date — показываем месяцы в родительном падеже, и решил тоже сделать решение, направленное на искоренение косноязычности при выводе дат. Друпал используют не все, кто использует PHP, а вот мое решение может заюзать любой пользователь PHP 5.2+.

                  Что же я такого там сделал?
                • Якорная навигация на jQuery (graceful degradation)

                    Недавно я наткнулся на интересный плагин для jQuery: BBQ — Back Button & Query Library.

                    И решил на ее основе сделать свой плагин для навигации на основе якорей. Задачи, которые я себе ставил:
                    1. нормальная работа ссылок в условиях выключенного javascript (читай — нормальная индексация страниц поисковиками)
                    2. поддержка обычных anchor-ссылок безо всяких дополнительных запросов
                    3. поддержка отображения подгруженного контента в разных областях страницы

                    Результат можно посмотреть здесь. А еще можно почитать чуть подробнее.

                    UPD: дамы и господа, некоторые жалуются на недоступность странички (403 Forbidden), однако, я ничего такого не вижу. В комментах привели ссылку на рабочий вариант, который можно попробовать, если моя ссылка у вас не заработала: http://vbolshov.org.ru.nyud.net/anchornav/.

                    как это использовать
                  • CSSопеды — велосипеды от CSS

                      К вопросу о Динамическом CSS. Расскажу вам историю.

                      Вася и Петя однажды заметили, что их новые велосипеды не такие классные, как им еще недавно казалось: когда едешь в гору, приходится тратить много сил, а иногда даже сходить с велосипеда и везти его самому. Ребята призадумались, ибо они были не пользователи дрожащие, а разработчики умелые.

                      Вася с честью вышел из ситуации. Он приделал к велосипеду лебедку. Теперь ему всего и надо было на подъеме, что сбегать быстренько наверх, закрепить трос, спуститься обратно и ехать в свое удовольствие (если, конечно, аккумулятор не забыл зарядить).

                      Петя был не столь изобретателен. Он ничего не приделывал. Но тоже добился своего (с грехом пополам, жалкий неудачник и ретроград). Прочитав Руководство Пользователя (вот до каких глубин позора опустился, нечестивец) — он научился пользоваться Коробкой Передач.
                    • Эмулируем ON DUPLICATE KEY UDPATE — подводный камень

                        В MySQL можно делать INSERT… ON DUPLICATE KEY UDPATE. В постгресе пока что такого нет (насколько мне известно, MERGE не вошел в версию 8.4).

                        Я натыкался в сети на рекомендацию использовать правила для того чтобы добиться аналогичного поведения. Мне показалось, что использовать правила в данном случае даже лучше, нежели MERGE, я сделал правило… и наткнулся на подводный камень. Я реализовывал счетчик: есть уникальный ключ и, если такой ключ в таблице уже существует при вставке новой записи — следует вместо этого увеличить значение счетчика.

                        Простая ситуация, простое правило. Но: при первой вставке это правило, как оказалось, тоже отрабатывает! В результате, при первой вставке вставляется не 1, а 2!

                        Пока писал, Fred84 подкинул ссылку, где об этой ситуации подробнее рассказано: archives.postgresql.org/pgsql-bugs/2007-03/msg00080.php
                        Под катом - простой SQL скрипт для воспроизведения проблемы
                      • PHP, Closures, use & references

                          Хочу рассказать об одной особенности использования замыканий в PHP-5.3. Думаю, для многих она покажется очевидной, но тем не менее. Оказывается, используя use ($var1,..) — мы можем передавать переменные по ссылке: use (& $var1,..).

                          Пример, иллюстрирующий возможные варианты использования (и просьба не тыкать носом в array_sum() ;) ):
                          $rows = array(1, 2, 3);
                          $total =  0 ;
                          // Случай раз - use ($total) без ссылки
                          array_walk($rows, function($row) use ($total) {
                                  $total += $row;
                          });
                          echo "Total is $total\n";
                          // Случай два - use (& $total) по ссылке
                          array_walk($rows, function($row) use (& $total) {
                                  $total += $row;
                          });
                          echo "Total is $total\n";

                          На выходе получим:
                          Total is 0
                          Total is 6

                          Enjoy!
                        • Continuous integration для php

                            Эту статью написал мой добрый приятель и бывший коллега fred, работающий в команде программистов над большим и сложным проектом, который должен работать 24х7. Если кто-то решит пригласить его на хабр — с удовольствием вышлю его email по хабрапочте. Пожелания и комментарии приветствуются, а я обязуюсь передавать ответы автора в меру своих возможностей.

                            Меня давно посещала мысль запустить CI-сервер для рабочего проекта. База модульных тестов уже достаточно внушительных размеров, а количество людей в проекте немного увеличилось. Можно было бы наблюдать за тем, как изменяется покрытие тестами кода и соблюдаются стандарты кодирования. И наказывать провинившихся. Шучу.
                            Некоторое время назад была прочитана книжка Непрерывная интеграция. Улучшение качества программного обеспечения и снижение риска и статья Quality Assurance Tools for PHP, которые и послужили отправной точкой.
                            Читать дальше →
                          • Казино делают ход конем?

                              По центральным каналам вовсю трубят о том, что казино и игровые клубы закрываются, их сотрудники остаются без работы и прочая, прочая…

                              А вот у нас в Обнинске ситуация такова: на месте бывших игровых клубов открываются т. н. «Интернет-клубы». Доступ в интернет с их помощью, вроде бы, осуществлять, действительно можно. Но это — не главный их бизнес. А главный — все те же игры, только вместо автоматов — персональные компьютеры.

                              Интересно, это наша обнинская специфика или в вашем городе та же чертовщина, %юзернейм%?

                              UPD: конечно же, я догадывался, что Обнинск не уникален в этом. И возмущению моему нет предела (тем более, что такое творится по всей стране, как говорят хабралюди): о том, что игровые клубы просто сменили вывеску — практически ни слова ни на одном канале. Типа «вот какие молодцы медведев и путин сотоварищи, отрубили голову чудовищу».
                            • Работа с датами

                                Часто приходится видеть, как начинается настоящий цирк, когда у PHP-программиста доходит дело до дат. Тут и самописные волшебные функции, которые что-то там вычисляют и постоянно спотыкаются на границе месяцев или годов, или на переводе часов на зимнее/летнее время, тут и таинственное использование встроенных функций, с бубнами и плясками.

                                А надо-то, на самом деле, почти всегда совсем немного.

                                Под катом — пара полезных, на мой взгляд, советов для начинающих программистов.

                                Читать дальше →
                              • Информация о встроенных классах и функциях из командной строки

                                  Может быть, то, о чем я собираюсь рассказать, уже всем известно, а может, и нет.

                                  В общем так: получить информацию о любом встроенном классе или функции (само собой, сюда входят и функции из любого включенного в вашей сборке расширения) — получить эту информацию можно с помощью простых команд.

                                  php --rc, php --rf, php --re, php --ri
                                • Фабрики — рабочим, Код — программистам!

                                    За годы профессиональной деятельности у меня сложилось мнение, что по большей части программный код пишется «на коленке», «впопыхах», «под страхом дедлайна» и прочая, прочая. Рефакторится этот код не то чтобы даже не всегда — а практически никогда. Такой код впоследствии бывает тяжело воспринимать. Я не жалуюсь, я понимаю, что таково положение вещей и оно едва ли кардинальным образом поменяется.

                                    Но! Есть вещи (само собой, давно известные, как и большинство других), о которых непростительно часто забывают разработчики, но которые способны сделать их самих, а также других людей, более счастливыми — когда придет время раскапывать код, написанный когда-то.

                                    Несколько простых правил, следуя которым, вы можете упростить жизнь свою и других в будущем
                                  • расширение zip, небольшой хинт

                                      В одном из моих проектов широко используется импорт различных данных в формате CSV. Когда-то данных было немного и всех устраивало непосредственно загрузить один-два не слишком больших файла. Со временем данных стало больше, выросли размеры импортируемых файлов и их количество. Решено было загружать файлы в ZIP-архиве: экономим трафик + имеем всего один аплоад вместо несольких.

                                      Для работы с архивом я воспользовался расширением zip. Описывать здесь, что к чему в этом расширении, я здесь не буду, это достаточно подробно описано в документации.

                                      Я расскажу лишь об одной особенности, которая оказалась для меня полезной. При импорте файла, который пользователь загружает в форме, сам по себе ZIP-архив на сервере ни к чему, да и распаковывать его тоже без надобности: потом ведь еще удалять придется. На помощь приходит метод ZipArchive->getStream(). Получаем с его помощью файл-хэндлер и можем спокойно скормить его, допустим, в fgetcsv.

                                      UPD. Наверное, не совсем понятно объяснил. Мне нужны данные из тех CSV-файлов, которые лежат в ЗИПе. И нужны мне эти данные в базе данных, а не в самих ЦСВшках и уж тем более не в архиве. То есть данные из ЦСВшек я импортирую в БД. Поэтому я беру тепленьким временный файл ( $_FILES['userfile']['tmp_name'] ). И прямо не распаковывая его, импортирую все содержащиеся в нем ЦСВшки в БД. После этого PHP сам позаботится о том, чтобы удалить архив, который больше уже не нужен.

                                      UPD. От хабраюзера Adelf: в некоторых случаях (не в моем) следует принимать во внимание факт того, что $_FILES['userfile']['tmp_name'] может быть недоступен из-за open_basedir

                                      Надеюсь, эта информация кому-нибудь окажется полезной.