Пример разработки блога на Zend Framework 2. Часть 2. Модуль MyBlog

Это вторая из трех частей статьи, посвященной разработке простого приложения при помощи Zend Framework 2. В первой статье я рассмотрел структуру ZendSkeletonApplication, а в этой части приведу пример разработки простого модуля. Третья часть будет посвящена работе с пользователями.

Установка и настройка дополнительных модулей

Первым делом хочу отметить, что установка стороннего модуля в Zend Framework обычно состоит из примерно таких четырех шагов:

  1. добавляем соответствующую строчку в composer.json, чтобы сообщить Композеру о новом модуле,
  2. выполняем команду php composer.phar update, чтобы Композер загрузил новый модуль и при необходимости перегенерировал автолоад файлы,
  3. добавляем новый модуль в список modules в файле config/application.config.php,
  4. при необходимости, размещаем конфигурационный файл модуля (обычно пример такого файла находится в папке config модуля) в config/autoload и делаем в нем необходимые правки.

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

Давайте начнем с установки простого, но полезного модуля Zend Developer Tools.

Читать дальше ➠

Пример разработки блога на Zend Framework 2. Часть 1. ZendSkeletonApplication

В последние несколько лет моя работа связана с использованием CMS Drupal, но на досуге я изучал и just for fun запускал проекты на питоновских фреймворках Django, Flask и Twisted. Сейчас я решил освоить основы двух-трех популярных PHP-фреймфорков и первыми я решил изучить Zend Framework 2 и Yii.

В процессе ознакомления с Zend Framework 2 я изучил туториал с официального сайта (http://framework.zend.com/manual/2.2/en/user-guide/overview.html), просмотрел документацию фреймворка (http://framework.zend.com/manual/2.2/en/index.html), прочитал книгу Michael Romer “Web development with Zend Framework 2” и собрал собственное тестовое приложение.

Переварив всю эту информацию, я пришел к мысли, что официальный туториал к фреймворку суховат:

  • в нем не рассказывается о работе с пользователями, сессиями и правами доступа,
  • лишь вскользь рассматривается такая основополагающая часть фреймворка как ServiceManager,
  • в качестве интерфейса с базой данных безальтернативно используется паттерн Table Gateway (и соответствующая его реализация в фреймворке),
  • используется встроенный в фреймворк шаблонизатор, который после питоновского Jinja 2 кажется совершенно неудобным и примитивным,
  • и т.д.

В итоге, более-менее удовлетворительное по функционалу приложение я смог создать после прочтения книги.

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

  • в качестве шаблонизатора будет использоваться Twig,
  • для работы с БД — Doctrine ORM,
  • для авторизации/аутентификации и распределения прав доступа я буду использовать существующие модули ZfcUser (https://github.com/ZF-Commons/ZfcUser) и BjyAuthorize (https://github.com/bjyoungblood/BjyAuthorize),
  • также я рассмотрю вопросы разработки собственных валидаторов форм, View плагинов и другие.

Статья написана новичком (в Zend Framework) для новичков, по этому приветствуется любая критика по делу и советы по усовершенствованию приложения.

Найти код проекта можно на Гитхабе: https://github.com/romka/zend-blog-example.

Статья будет разбита на 3 части:

  • в первой (текущей) части я рассмотрю структуру ZendSkeletonApplication,
  • во второй части разберу разработку собственного модуля (формы, работа с БД при помощи Doctrine ORM, разработка View-плагина),
  • третья часть будет посвящена работе с пользователями.

Итак, приступим.

Читать дальше ➠

Проблема с кодом вне функций в Drupal 6 и 7

Столкнулся с интересной проблемой, которую удалось повторить и в Drupal 6, и в Drupal 7. В модуле вне тела функции была объявлена константа:

define('TEST_CONST', drupal_get_path('module', 'test_module'));

(тут дело даже не в самой константе, а в использовании апишной функции drupal_get_path() вне тела функции).

Этот модуль долгое время корректно работал, до тех пор пока в нем не был объявлен hook_exit(). После этого события Друпал начал отдавать ошибку "PHP Fatal error: Call to undefined function drupal_get_path() in...", где вместо drupal_get_path() можно поставить почти любую функцию из Drupal API, которая была использована в коде, расположенном вне тела функций.

Поиск и исправление причин ошибки осложнился тем, что она стала проявляться не сразу после добавления hook_exit(), а спустя некоторое время.

Суть ошибки оказалась в следующем:

  • Друпал в таблице system, модулям которые реализуют hook_exit(), проставляет значение 1 в колонке bootstrap, по умолчанию этот параметр равен нулю.
  • В свою очередь модули отмеченные таким образом начинают загружаться Друпалом раньше остальных (на этапе DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE в случае Drupal 6) когда API, в частности файл common.inc, содержащий функцию drupal_get_path(), еще не загружен полностью.
  • Загрузка модуля подразумевает include файла модуля и, что логично, исполнение кода, находящегося вне тела функций.

Таким образом, после добавления hook_exit() модуль стал загружаться до полной загрузки API и функция drupal_get_path() на этом этапе действительно еще не была определена. Решилась проблема переносом проблемного кода в hook_init().

Возникла ошибка не сразу от того, что обновление поля bootstrap в таблице system делается не сразу, а при обновлении кеша списка модулей (вызов функции module_rebuild_cache() в Drupal 6). Этот кеш очищается, например, при нажатии кнопки “Сохранить” на странице списка модулей или при срабатывании модуля Update status.

Похвастаюсь статистикой в день сообщения о разводе Путина

Средняя нагрузка на сайт днем в рабочий день 1000 запросов в минуту (масимум 30-40 в секунду), около 200 тысяч уников в день и около 800 тысяч просмотров. Трафик отдается на скорости до 10 мегабайт в секунду.

В пиках нагрузка раньше доходила до 4 тысяч запросов в минуту (до 120 в секунду), около 350 тысяч уников в день и 2,5 млн. просмотрв. В пиках трафик отдавался на скорости до 50 мегабайт в секунду.

Пятница, 7 июня. В пике сайт отдавал больше 12 тысяч страниц в минуту (250 в секунуду) на скорости около 110 мегабайт в секунду.

visitors Traffic by minutes First frontend Second frontend

Drupal + Varnish отработали на отлично. С учетом нашего канала и железа сайт может держать вдвое большую нагрузку подобного плана.

Quickpong — онлайн версия игры Pong

Разработал и запустил на домене quickpong.com онлайн версию игры Pong. В игре (by design) реализован только режим мультиплейера, то есть игра идет не против искусственного интеллекта, а против другого человека.

Игра представляет из себя клиент-серверное приложение, серверная часть написана на питоновском фреймворке Twisted, клиентская — на флэшовом фреймворке FlashPunk.

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

Читать дальше ➠

Интеграция системы статистики Piwik с Drupal 6

При работе над Drupal-проектом у меня возникла необходимость сбора детальной статистики о просмотрах материалов и вывода этой статистики в виде блоков, отображающих самые просматриваемые материалы за последние день, неделю и месяц. Стандартный друпальский модуль Statistics (и в шестом, и в седьмом Друпале) для решения такой задачи абсолютно неприменим:

  • во-первых он осуществляет сбор статистики на hook_exit() и не будет работать корректно со сколько-нибудь серьезными системами кеширования, например при использовании Varnish или модуля Boost.
  • во-вторых модуль Statistics собирает статистику за всё время существования материала, сделать выборку вида: “сколько раз был просмотрен материал за последний день” с этим модулем невозможно. По этому при использовании этого модуля исходную задачу пришлось бы модифицировать к виду: вывести список самых просматриваемых материалов созданных за последние день, неделю или месяц, но этот подход неприемлем, так как на сайте существуют материалы старше месяца, способные попасть в топ по просмотрам.

Таким образом, возникла необходимость внедрить полноценную систему статистики и интегрировать ее с Друпалом. Под полноценными системами я понимаю сервисы типа Google Analytics или Яндекс.Метрика, используя API которых можно запросить статистику просмотров материалов за любой диапазон дат. Достоинством этих сервисов является то, что они у себя хранят всю статистику, а она на посещаемом ресурсе может занимать немало места, их недостаток — все таки это внешние сервисы и неизвестно, что с ними случится завтра: сломаются, станут платными, не захотят внедрять нужную пользователю фичу и т.д.

В итоге я решил установить на собственном сервере open source систему статистики Piwik и интегрировать ее с Друпалом. Да, Пивик пока местами уступает GA и Я.М в гибкости отчетов (хотя есть в нем и отчеты, которых нет ни в ГА, ни в Я.М), но, во-первых, нужную мне задачу он решает, во-вторых он постоянно развивается своими разработчиками и может быть расширен с помощью самописных плагинов.

Для седьмого Друпала есть замечательный модуль Piwik stats, интегрирующий Друпал с Пивиком. Суть модуля состоит в том, что он создает специальное поле, которое может быть прикреплено к любой entity (материалу, пользователю). В настройках поля задается параметр, отвечающий за то, статистика за сколько дней должна быть в этом поле. Одна entity может содержать несколько полей с разными настройками, то есть, например, каждый материал может содержать три поля с информацией о просмотрах за последние день, неделю, месяц, как раз то что мне и требовалось.

Заполнение полей данными осуществляется через Drupal Queue API по крону, но при желании стандартный механизм обработки очереди может быть заменен чем угодно, например Rabbit MQ.

Плюсом хранения статистики в полях является то, что статистика становится прозрачно интегрированной со всем модулями Друпала, например с Views, с помощью которого, в том числе, можно строить блоки с контексто-зависимой статистикой. То есть, например, на главной странице сайта выводить список самых популярных статей со всего сайта, а на странице статьи или раздела — выводить самые популярные статьи текущего раздела.

Основная проблема для меня состояла в том, что модуль Piwik stats работает только под седьмым Друпалом и его разработчик не планировал делать бэкпорт под шестерку, а проект, в котором мне понадобился этот функционал, работает как раз на древней шестой версии Друпала. По этому я сам сделал бэкпорт этого модуля под шестерку. Забрать мою версию модуля можно из sandbox-проекта Piwik_stats, обсуждение этого бэкпорта с автором основного модуля тут: http://drupal.org/node/1736398.

Пока мейнтейнер модуля не хочет делать мою версию модуля официальной, из-за того, что требуется сделать детальный code review. Тем не менее, мой модуль без нареканий больше месяца работает в бою на двух Друпал 6 проектах.

Typo — Drupal-модуль для борьбы с опечатками на сайте

Разработал новый модуль для Drupal 7, который позволяет пользователю выделить мышью найденную в тексте опечатку и нажатием Ctrl + Enter отправить сообщение о ней администратору сайта. Модуль не зависит от внешних сервисов типа Орфуса и тесно интегрирован с популярными модулями Друпала такими как Rules, Token, Views и Views bulk operations.

Интеграция с модулями Rules и Token, позволяет, например, настроить отправку сообщений о найденных ошибках по е-мейлу, в системный журнал или вызвать любое другое действие, доступное в модуле Rules. С помощью токенов [typo:url], [typo:text] и [typo:comment] в текст сообщения можно включить информацию об опечатке.

Интеграция с Views позволяет сделать вывод списка ошибок на странице, в комплекте с модулем уже идет настроенное представление, а интеграция с Views bulk operations позволяет удалять из этого представления обработанные сообщения.

По умолчанию, все сообщения старше 3 дней автоматически удаляются, но это действие можно отключить в настройках модуля.

Popup-окно с формой отправки опечатки выводится модулем Ctools и его вид может быть изменён как правкой CSS-файла, так и правкой соответствующего tpl-файла. Ctools — это единственная зависимость модуля, остальные модули (Rules, Views, etc) нужны только если вы хотите использовать соответствующий функционал.

Скачать модуль можно на странице проекта: http://drupal.org/project/typo.

Испытать этот модуль вы можете прямо на этом сайте, список отправленных отчетов об опечатках доступен всем посетителям здесь: http://romka.eu/typo-reports (на реальном сайте к этому представлению анонимам лучше не давать).

upd Модуль упомянули в обзоре в блоге Cocomore, жду наплыва установок на агнлоязычных сайтах :)

Гусеничная платформа на Arduino, управляемая с Android-смартфона

Я никогда не имел опыта в программировании микроконтроллеров, по этому давно хотел сделать какую-нибудь поделку на Arduino. Ардуино — это очень простая в освоении платформа, к которой легко подключить внешние датчики (дальномеры, гироскопы, акселерометры, датчики температуры и освещенности и т.п.) и устройства: моторчики/сервоприводы и т.п.

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

Катализатором, который заставил меня перейти от мыслей к делу стала вот эта серия статей на Хабре: http://habrahabr.ru/post/133414/, http://habrahabr.ru/blogs/DIY/135371/, http://habrahabr.ru/post/136224/. Я решил собрать аналогичную платформу, только управляемую не джойстиком, а Python-приложением с компьютера и с Android-смартфона. В дальнейшем хочу дописать серверный софт, который позволит управлять платформой через браузер и видеть в нем изображение с камеры. Именно для этого первая версия приложения для компа пишется на Питоне, чтобы проще было перенести код в веб.

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

Читать дальше ➠

Путешествие по Европе весной 2012. Германия — Франция — Италия

Я уже несколько раз бывал в Европе, но обычно попадал сюда на новогодние каникулы, а в это время погода здесь, как и в России, не самая лучшая, по этому я давно мечтал сгонять в Европу весной, в мае, когда природа расцветает и пейзажи становятся не такими унылыми как зимой.

В этом году в начале мая мне выдалсь возможность на три дня съездить в комадировку в Берлин, после чего я остался в Европе в отпуск на две недели и прокатился по Германии, Франции и Италии с заездом в Люксембург и Монако.

Примерный маршрут был спланирован заранее и выглядел примерно так: сначала 3 дня в Берлине в деловой поездке, затем еду на поезде во Франкфурт, там встречаюсь с другом, кототрый приедет туда из Милана на арендованной машине. Далее едем из Франкфурта через Страсбург и Люксембург в Париж, после пары дней в Париже держим путь на юг Франции в Марсель, из Марселя по Лазурному Побережью в сторону Италии (там это побережье зовется Лигурийским) и затем в Милан, а из Милана самолетом в Москву.

Билет в Берлин мне оплачивала компания, обратно летел за свой счет, но это даже и хорошо, так как я получил возможность лететь обратно откуда мне удобно, а не из Берлина. Билет на поезд в первый класс из Берлина во Франкфурт я купил сильно заранее до поездки и он обошелся мне всего в 65 евро, если бы брал его день в день, то пришлось бы раскошелиться на 145 евро за первый класс или 125 за второй (билет брал тут: http://bahn.de).

Читать дальше ➠

Пример конфигурационного файла Varnish

Как обещал в докладе выкладываю пример и описание рабочего конфига для Варниша. Чтобы узнать подробнее о том, что такое Варниш и для чего он нужен ознакомьтесь с разделом Pressflow + Varnish.

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

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

Читать дальше ➠