Ребята из Yii Software готовят бомбу. Пока я лишь наблюдаю за новой версией фреймворка из-за угла, но уже вижу улучшения во всём — от использования новых возможностей языка до удобного создания собственных структур для крупных проектов.
Однако в настоящее время дела обстоят таким образом, что поезд только встаёт на рельсы (не ищите аналогий, хотя они тут есть) и стабильную версию ещё придётся подождать, а новые проекты нужно делать уже сегодня. Для счастливой разработки не хватает совсем немного, а именно — удобной структуры приложения, развёртывания без лишних проблем, ну и разных плюшек по желанию. На данный момент наиболее приятным решением является Yiinitializr.
Yiinitializr — библиотека, помогающая упростить и ускорить цикл разработки приложения на основе фреймворка Yii. Из коробки доступны 3 варианта структурных шаблонов:
Basic — создан для проектов небольших масштабов;
Intermediate — подойдёт для большинства проектов средней сложности;
Advanced — будет хорошим выбором для более сложных проектов с необходимостью предоставления собственного API.
Почему стоит ознакомиться с этой статьёй? Отсутствие доходчивой документации вводит ещё неискушённых разработчиков в ступор (проверено на себе), а куча различных сюрпризов (например, в виде багов) замечательно дополняют это ощущение. Я попытался разобрать процесс работы с Yiinitializr до винтиков, чтобы уберечь вас от большинства неприятностей на пути его освоения.
На этом, я думаю, описательных слов достаточно. Если вы читаете эту статью, значит вы уже, скорее всего, знаете, что такое Yiinitializr, и хотите получить ответы на конкретные вопросы по его использованию. А если всё-таки ещё не знаете, то основную суть, я надеюсь, вы уловили, так что не бойтесь читать дальше.
Внимание! Так как Yiinitializr продолжает развиваться (хоть и крайне медленно), любой баг или любое поведение описанное в этой статье могут быть исправлены/изменены на момент прочтения. Не исключено даже появление нового более совершенного инструмента (например, встроенных возможностей второй версии фреймворка).
Установка
Шаг 1. Загрузка Yiinitializr
Перво-наперво Yiinitializr необходимо скачать. Сделать это можно двумя способами — с официального сайта, либо из репозитория на GitHub (Basic, Intermediate, Advanced). Воспользовавшись первым способом, мы получаем возможность добавить в пакет различные расширения для Yii, но по какой-то причине сборка Intermediate-шаблона происходит на основе старой версии Yiinitializr, содержащей неправильный инициализирующий скрипт (Внимание! Это касается только Intermediate-шаблона). Вместе с тем, исходники из главной ветки репозитория предлагают нам другой неприятный сюрприз, а именно — лишняя зависимость в конфигурационном файле Composer, из-за которой во время установки происходит ошибка. Но не стоит отчаиваться, вместе мы точно сможем решить эти проблемы.
Итак, в зависимости от того, какой способ вы выбрали, открывайте соответствующий спойлер.
Я скачал архив с официального сайта
Сейчас нам придётся забежать немного вперёд. Но чтобы не терять нить повествования, мы лишь исправим инициализирующий скрипт, а все разъяснения оставим на потом.
Распаковываем архив и меняем содержимое двух файлов. Содержимое ./frontend/www/index.php на:
С инициализирующим скриптом у нас всё в порядке, но необходимо избавиться от лишней зависимости Composer. Для этого открываем файл ./composer.json и удаляем строчку.
"2amigos/yiistrap": "dev-master",
из блока require.
Теперь, когда актуальная версия свежескачанного Intermediate-шаблона Yiinitializr у нас на компьютере, предлагаю изучить его структуру (с двумя другими версиями дела обстоят аналогичным образом, так что трудностей с пониманием возникнуть не должно). Приложение разделено на 4 части (<part>):
backend и frontend — здесь всё ясно без пояснений;
console — часть для консольных команд;
common — место для общих компонентов всех остальных частей. Например, сюда мы можем положить модель, которая будет использоваться в backend- и frontend-частях, либо SiteController с общими правилами для всего приложения.
На что следует обратить внимание:
Использование отдельной конфигурации для каждой из частей. Подробности на следующем шаге.
Инициализирующий скрипт — точка входа в приложение. Для каждой из backend- и frontend-частей приложения он свой и находится в директории ./<part>/www/.
Сам Yiinitializr, а также все библиотеки, установленные через Composer лежат в директории ./comon/lib/. Библиотеки со своими зависимостями появятся в поддиректории vendor после завершения установки.
Миграции, после создания, аккуратно складываются в директорию ./console/migrations/.
Шаг 2. Предварительная настройка
Следующим шагом по нашему плану идёт предварительная настройка приложения. Количество конфигурационных файлов впечатляет:
Подобное разделение позволяет нам разграничить настройки приложения, во-первых, по частям (<part>), а, во-вторых, по окружению (<environment>).
Часть (<part>) — это структурная единица приложения, отвечающая за определенные задачи. Окружение (<environment>) — это режим, в котором работает сайт. По-умолчанию: dev (режим разработки) и prod (рабочий режим).
После установки (или обновления) создаётся файл ./<part>/config/env.php в который копируются настройки из ./<part>/config/env/<environment>.php. Далее, при каждом запуске нашего приложения, конфигурационные файлы будут динамически собираться воедино. Изначально, для меня было загадкой, по какому принципу происходит сборка. Ответ оказался вполне логичным:
Единственная обязательная настройка, которую нужно произвести именно на этом шаге — настройка соединения с базой данных. Для этого задаём в файле ./comon/config/env/dev.php свои данные для подключения. Мы выбрали этот конфигурационный файл по причине того, что сейчас работаем в режиме разработки, а база данных у нас единая для всех частей приложения.
Всё сделали? Отлично! Можем переходить к следующему шагу.
Шаг 3. Установка с помощью Composer
Предлагаю перечислить дополнительные возможности Yii, без применения которых не удастся реализовать полноценное приложение:
Использование расширений.
Тестирование с помощью PHPUnit и Selenium. Yii предоставляет нам дополнительные классы для тестирования.
Изменение структуры базы данных путём создания миграций. В Yii эта возможность реализована с помощью консольной команды, поэтому к этому же пункту мы отнесём использование любых других пользовательских консольных команд.
Раз Yiinitializr осуществляет связь с фреймворком через Composer, то давайте пойдём этой же дорогой для реализации всех вышеперечисленных пунктов.
Внимание! Конечно же, в своём проекте вы можете пользоваться любым другим способом установки библиотек для разработки, таких как PhpUnit. Я предлагаю такой вариант в качестве одной из альтернатив, и если у вас есть свои причины, чтобы выбрать другой путь, то никто не запрещает. Этот вариант не является единственным правильным.
Composer — менеджер зависимостей для PHP. С его помощью мы можем легко настроить все необходимые расширения как в целом для проекта, так и для конкретного окружения.
Для начала давайте откроем файл ./composer.json. О его структуре вы можете прочитать по ссылке выше, нас же сейчас интересует только раздел require:
Здесь указаны следующие зависимости — последняя на момент написания статьи версия самого фреймворка Yii, а также два расширения (второе является зависимостью первого и поэтому явно не указывается) от авторов Yiinitializr: Yiistrap — Twitter Bootstrap для Yii, Yiiwheels — продвинутые компоненты для Yiistrap. В названyiiях уже можно запутаться. Расширения, указанные в этом блоке нам нужны для работы приложения. Таким же образом вы можете добавлять расширения, необходимые именно для вашего проекта, но пока нам достаточно и этих. Теперь перейдем к библиотекам, которые нам понадобятся в процессе разработки. Этими библиотеками является PhpUnit с дополнениями.
Здесь есть один интересный момент. Для работы библиотеки php-invoker необходимо PHP-расширение ext-pcntl, которое [на данный момент] работает только под Unix платформами. Поэтому пользователям Windows необходимо сделать небольшой хак, добавив в блок repositories следующие настройки для загрузки php-invoker не в виде пакета Composer, а в виде репозитория Git:
Внимание! Для установки зависимостей PhpUnit в системе должна быть установлена и добавлена в %PATH%система контроля версий Git.
Наконец-то мы можем перейти непосредственно к установке всего этого добра в проект, а также настройке окружения. Для этого воспользуемся Composer. Если он не установлен в вашу систему, то не беда, т. к. в виде phar-архива он распространяется вместе с Yiinitializr.
Переходим в рабочую директорию проекта. Перед запуском Composer необходимо обновить:
> php composer.phar self-update
Теперь приступаем непосредственно к установке нашего проекта:
> php composer.phar install
Внимание! Не забывайте, что PHP использует разные настройки для разных сред запуска. Если у вас выскакивают ошибки соединения с базой данных, загрузкой через SSL или таймауты, то проверьте какую конфигурацию использует PHP.
На вопрос о начале установки отвечаем положительно:
Start Installation? [y/n]: y
Расширения начали скачиваться, процесс пошёл. Далее нас спросят об окружении в котором мы собираемся работать. Сейчас мы находимся в режиме разработки, поэтому пишем dev или просто нажимаем Enter:
Please, enter your environment -ie. "dev | prod | stage": [dev]: dev
Поздравляю, Installation completed!
Что же сделал Composer?
В зависимости от выбранного окружения создал конфигурационные файлы env.php.
Создал временные папки: runtime, assets.
Установил зависимые расширения.
Заблокировал окружение.
Создал автозагрузчик для автоматического подключения необходимых файлов (эта тема относится к возможностям Composer и сейчас для нас серьезной роли не играет).
В заключение выполнения установки Composer автоматически вызвал команду migrate, которая создала в вашей базе данных таблицу {{migration}} для хранения метаданных миграций. Именно поэтому нам было необходимо настроить соединение с базой данных на прошлом шаге.
Сейчас самое время разобрать, что же означает выражение «заблокировал окружение» (4 пункт). При разработке с использованием Yiinitializr и Composer, может потребоваться обновить зависимости. Чтобы не приходилось каждый раз вручную указывать текущее окружение, разработчики решили заблокировать проект с помощью файла env.lock (./common/lib/Yiinitializr/config/env.lock). Пока он находится на своём месте, никакие лишние вопросы при обновлении не побеспокоят вас.
Внимание! Не следует изменять настройки в файлах ./<part>/config/env.php, т. к. этот файл исключен из-под наблюдения Git и при следующем обновлении проекта, файл «перезапишется». Для изменения настроек окружения используйте только предназначенные для этого файлы конфигураций ./<part>/config/env/<environment>.php.
Некоторые возможности Yiinitializr
В этом разделе давайте ещё раз вместе окинем взглядом Yiinitializr, остановившись более подробно на некоторых его возможностях.
Yiinitializr — это библиотека, подключив к проекту которую, мы можем более гибко настраивать структуру приложения. В базовой версии, разработчики предоставляют нам 3 готовых шаблона, подходящих для большинства проектов. Каждый из шаблонов основан на Initializr и соответственно включает в себя Twitter Bootstrap, Modernizr и JQuery. Из коробки сайт лишён всякой динамики и представляет собой статичную Initializr-страничку.
Идём дальше. Разработчики Yiinitializr написали своё видение базовых классов, которые предлагают расширять нам в своих приложениях. Посмотрите на них /common/extensions/components/ и решите, нужны ли вам эти возможности, прочитав небольшое описание.
EWebApplication — расширенный вариант стандартного CWebApplication. В комментариях к методам довольно понятно расписаны проблемы, которые эти методы решают. Как мы знаем, менять исходный код библиотек, для изменения поведения является плохим тоном, однако я не нашёл более изящного способа для использования EWebApplication, кроме как заменить ~46 строчку в файле ./common/lib/Yiinitializr/Helpers/Initializer.php с
EActiveRecord — расширенный вариант стандартного CActiveRecord, добавляющий сеттеры и геттеры для удобной работы с именами форм, таблиц и списков (необходимо для EController), а также группу методов для логирования изменений данных модели.
EController — привносит принцип DRY в наши классы контроллеров, вынося из них методы loadModel и performAjaxValidation, а также добавляет ещё ряд приятностей. В общем изучайте сами, что-нибудь да пригодится.
Внимание! Использование вышеперечисленных классов, к сожалению, убирает возможность генерировать CRUD через Gii. Как решить эту проблему смотрите в FAQ.
Мы уже видели, что Yiinitializr собирает конфигурационный файл из нескольких частей. Как же этим можно воспользоваться? Например, можно включить debug-режим для разработки, и отключить его для рабочей копии проекта. Больше нет необходимости следить за debug-константами, всё можно сделать с помощью конфигурационных файлов.
Для этого используется раздел конфигурации params. Нам доступны следующие параметры:
yii.debug;
yii.traceLevel;
yii.handleErrors;
php.defaultCharset;
php.timezone.
При каждом запуске приложения, значения этих параметров будут автоматически приниматься в действие. Теперь, я думаю, стало понятно, как решить нашу задачу с включение/выключением debug-режима. В файлe ./common/config/env/dev.php мы его включаем:
Внимание! Эти настройки лучше произвести до установки через Composer. Если же вы сделали это после, то необходимо удалить файлы ./common/config/env.php и ./common/lib/Yiinitializr/config/env.lock, а затем выполнить
> php composer.phar update
Также, следите, чтобы эти настройки не перекрывались в других конфигурационных файлах.
Развёртывание приложения
Наконец пришло время выкатить нашу разработку в производство. У вас могут быть свои решения для развёртывания PHP-проектов, мы же рассмотрим этот процесс со стороны Yiinitializr.
Предполагается, что мы возьмём наш проект из Git-репозитория, например, с помощью клонирования:
> cd projects
> git clone yiinitializr yiinitializr-prod
Cloning into 'yiinitializr-prod'...
done.
Благодаря файлу .gitignore в корне, мы получили чистую версию проекта, без временных директорий, конфигураций окружения и библиотек. Теперь, по знакомой схеме, просто запускаем установку через Composer с ключом --no-dev, и в качестве окружения выбираем уже prod:
> php composer.phar install --no-dev
Собственно, вот и всё, теперь спокойно можно отправлять проект на сервер (если вы производили действия этого раздела на локальной машине).
Вопросы и ответы
Есть ли перспективы?
Перспективы у Yiinitializr несомненно есть, однако снизившаяся практически до нуля скорость разработки делает их довольно туманными, особенно учитывая наличие большинства возможностей во второй версии фреймворка. Но на самом деле, сейчас не хватает ещё совсем немногих доработок, чтобы использование Yiinitializr приносило только удовольствие.
Почему генератор кода Gii не создаёт CRUD?
Если вы решили использовать сторонние классы EActiveRecord и EController, то вас поджидает небольшое разочарование — вы не сможете воспользоваться генератором кода Gii для создания CRUD из-за различий в структуре классов.
Проблема решается просто — расширением Gii, с помощью подключения собственного шаблона кода. Я подготовил для вас рабочий вариант.
Распаковываем архив в директорию ./common и добавляем её в качестве пути поиска генераторов в конфигурацию ./common/config/env/dev.php:
Теперь, щёлкнув на поле Code Template на странице Crud Generator, должен появиться выпадающий список, содержащий наш набор шаблонов yiinitializr-simple.
Я изменил настройки в файле конфигурации окружения, но ничего не поменялось.
Как мы уже говорили, не следует изменять настройки в файлах ./<part>/config/env.php, т. к. этот файл исключен из-под наблюдения Git и при следующем обновлении проекта, файл «перезапишется». Для изменения настроек окружения используйте только предназначенные для этого файлы конфигураций ./<part>/config/env/<environment>.php. Эти настройки лучше произвести до установки через Composer. Если же вы сделали это после, то необходимо удалить файлы ./common/config/env.php и ./common/lib/Yiinitializr/config/env.lock, а затем выполнить
> php composer.phar update
Также, следите, чтобы эти настройки не перекрывались в других конфигурационных файлах.
Как разместить сайт на основе Yiinitializr на виртуальном хостинге?
Поставить сайт на основе Yiinitializr на виртуальный хостинг не составит труда, несмотря на разные инициализирующие скрипты для разных частей приложения. Нам необходимо каждую из директорий ./<part>/www/ назначить в качестве DocumentRoot для доменов. Например, в ISP Manager это можно сделать, назначив корневую директорию вида /www/yiinitializr/frontend/www для создаваемого WWW домена.
Внимание! В зависимости от настроек хостинга, сайт может всё равно не работать, выдавая различные ошибки. Первым делом посмотрите в сторону файла ./<part>/www/.htaccess. Всеобъемлющие настройки могут сыграть злую шутку, поэтому при возникновении проблем, попробуйте удалить его, посмотрев на результат.
Почему вылетает Access forbidden при заходе в backend?
Потому что в ./backend/ зачем-то лежит файл .htaccess с инструкцией deny from all. Не знаю, есть ли в этом какой-то сакральный смысл, поэтому просто удаляем его. Вуаля!
Как добавить свои консольные команды для автоматического исполнения через Composer?
Эти настройки выполняют команду `./yiic migrate` во время событий post-install и post-update.
Также мы имеем возможность вешать консольные команды на события установки/обновления конкретных пакетов. Для этого в конфигурацию нужно добавить настройку следующего вида <vendor/<packageName>-<action>, например:
По аналогии мы можем добавлять свои консольные команды, используя все доступные события: pre-install, post-install, pre-update, post-update, post-package-install, post-package-update.
Можно ли сделать свой шаблон?
Вообще говоря, Yiinitializr — это отдельная библиотека, на базе которой можно разработать шаблон с любой структурой приложения. Однако подобная тема выходит за рамки данной статьи.
Так что с тестированием?
Да-да, я не забыл, что мы хотели проводить тестирование с использованием PhpUnit, установленного с помощью Composer. О самих принципах тестирования Yii читайте в официальном руководстве, здесь же мы рассмотрим запуск связки PhpUnit + Composer.
Как и раньше, мы разделим тестовые классы по частям приложения. Само тестирование ничем не отличается от стандартного, нас будут интересовать только две вещи, во-первых, загрузчик тестов, а, во-вторых, запуск самого PhpUnit.
Начнём с первого. Так как проект построен на основе Yiinitializr, то загрузчик тестов должен быть похожим на этот:
Обратите внимание, мы импортируем тестовые классы и подключаем дополнительный конфигурационный файл под названием test.php с отключением обработки ошибок.
Переходим ко второму пункту. Вот как будет выглядеть процесс тестирование для фронтенда:
> cd .frontendtests
> ....commonlibvendorbinphpunit .
P. S. Буду рад увидеть в комментариях ваше мнение по данной теме, дополнения, примеры из вашей практики, а также указания на неточности в статье. Спасибо!