Привет, %username%.
В сети встречал много вопросов касательно того, как бы правильней писать приложения с замечательным фреймворком Yii. Хочу поделиться своим видением данного вопроса… Всех заинтересованных — прошу под кат.
Статья подразумевает, что Вы понимаете, что такое компоненты, контроллеры и так далее.
Начнем со структуры приложения. Так как статья для начинающих, то ограничимся одной папкой приложения (более опытные пользователи могут разделить на common, frontend, backend, api,… и так далее).
Мы вынесли директории приложения и фреймворка на уровень ниже, ибо нет смысла делать их доступными для конечного пользователя.
Начнем по ходу выполнения приложения. Не хочу сюда копировать тонны кода — предлагаю Вам подглядывать исходные коды файлов из репозитория. Так же надо скопировать папку framework из дистрибутива Yii — незачем хранить целый фреймворк в репозитории, за исключением случаев, когда вносятся ручные изменения в исходники.
web/index.php — наш входной скрипт. Как видно из комментариев, сначала инициализируем вспомогательные константы, конфигурируем PHP, определяем вспомогательные функции Yii и оборачиваем запуск приложения в функцию, чтобы не плодить 9000 глобальных переменных.
Остановим внимание на компиляции конфига. Он собирается с помощью функции CMap::mergeArray, которая рекурсивно склеивает массивы, что очень удобно в нашем случае.
Дальнейшие настройки приложения выходят за рамки этой статьи, лишь добавлю, что мы используем обертку над стандартным компонентом Request и Controller.
В репозитории нет файла app/config/local.php. Его прототип лежит в app/config/local.example.php — там хранятся настройки подключения к базе данных и кэширования. Это сделано по двум причинам:
Есть еще один нюанс — app/config/params.php (будем использовать в следующей статье) подгружаем не сразу, а после инициализации приложения — это сделано для того, чтобы внутри него мы могли использовать компоненты приложения, такие как user.
basePath — путь к папке приложения, по которому будет создан алиас пути «application».
import — список алиасов и путей, которые будут использоваться автозагрузчиком классов. По данным маскам мы подключаем папки app/components и app/models.
preload — компоненты, которые надо инициализировать сразу. Иначе компонент будет инициализирован при первом обращении (lazy load).
components — собственно, самый ужас для начинающих, давайте разбираться. :)
log — логирование (с) к.о. В режиме dev собираем логи по категориям info и trace (за исключением вызовов system.CModule, чтобы не плодить component xxx loaded ...) в консоль браузера, а так же логи по профайлингам. В режиме продакшн пишутся логи ошибок и предупреждений в app/runtime/application.log (по умолчанию для CFileLogRoute).
request — компонент request, включаем защиту от csrf и ожидаем хэш по ключу «h» для POST/PUT/DELETE запросов. Класс переопределен на Request — он выполняет дополнительные манипуляции над входящими данными. Обратите внимание, если бы мы не подключили папку «application.components.*» в импорте, то в данном поле «class» пришлось бы писать «application.components.Request».
session — сессии. Используем класс CCacheHttpSession для хранения сессий в кэше, в нашем случае — memcache. Если вы используете несколько компонентов кэширования, скажем cache и cache2, и хотите хранить сессии в cache2 — используйте настройку cacheID (к слову, такая настройка есть у всех компонентов, которые так или иначе используют кэш). Так же мы указали, что сессии должны быть в режиме HttpOnly.
urlManager — ака роутер. Используем формат «path» для роутинга в виде /foo/bar. Параметр «useStrictParsing» говорит, что следует использовать правила только из поля «rules», иначе попробует загрузить пару controller/action для запрошенного пути. «showScriptName» — я использую значение IN_DEV, которое подставилось в единичку, чтобы во время разработки генератор ссылок (о нем в следующей части) добавлял index.php перед созданными ссылками — "/index.php/controller/action?foo=bar" вместо '/controller/action?foo=bar". И последнее поле, «rules» — ничего заоблачного, все великолепно описано в документации.
db — компоненты для работы с базой данных. Параметры «enableParamLogging» и «enableProfiling» подставились из конфига dev.php, то есть в режиме продакшн эти настройки использоваться не будут, а наоборот, добавится кэширование схемы баз для увеличения производительности.
cache — кэширование. Используем старый добрый надежный memcache. Внимание! Пользователи комплекса open-server иногда могут наблюдать ошибки вроде «Memcache pool ...», если не указано поле «servers» для кэширования через адаптер «memcache». Это можно исправить. Замените «localhost» на «127.0.0.1» в framework/caching/CMemCache:101
Хотел бы добавить, что по сути все компоненты Yii — это объекты определенного класса, а все настройки — зачастую его свойства.
Внимательней читайте документацию, все замечательно и понятно расписано.
Для корректной работы в IDE файл «framework/yiilite.php» следует помечать как текстовый, либо игнорировать.
Так же я всегда ингорирую, либо исключаю папки «framework/cli», «framework/gii», «framework/vendors», «framework/web/js/sources». Иначе возможны проблемы с автокомплитом php/js.
Пока что все, надеюсь кому-то эта статья будет полезной. В следующей части расскажу о нескольких виджетах, моделях и кэшировании.
До встречи.
В сети встречал много вопросов касательно того, как бы правильней писать приложения с замечательным фреймворком Yii. Хочу поделиться своим видением данного вопроса… Всех заинтересованных — прошу под кат.
Статья подразумевает, что Вы понимаете, что такое компоненты, контроллеры и так далее.
Структура
Начнем со структуры приложения. Так как статья для начинающих, то ограничимся одной папкой приложения (более опытные пользователи могут разделить на common, frontend, backend, api,… и так далее).
Структура приложения

Мы вынесли директории приложения и фреймворка на уровень ниже, ибо нет смысла делать их доступными для конечного пользователя.
Начнем по ходу выполнения приложения. Не хочу сюда копировать тонны кода — предлагаю Вам подглядывать исходные коды файлов из репозитория. Так же надо скопировать папку framework из дистрибутива Yii — незачем хранить целый фреймворк в репозитории, за исключением случаев, когда вносятся ручные изменения в исходники.
Инициализация/запуск
web/index.php — наш входной скрипт. Как видно из комментариев, сначала инициализируем вспомогательные константы, конфигурируем PHP, определяем вспомогательные функции Yii и оборачиваем запуск приложения в функцию, чтобы не плодить 9000 глобальных переменных.
Остановим внимание на компиляции конфига. Он собирается с помощью функции CMap::mergeArray, которая рекурсивно склеивает массивы, что очень удобно в нашем случае.
Дальнейшие настройки приложения выходят за рамки этой статьи, лишь добавлю, что мы используем обертку над стандартным компонентом Request и Controller.
Примечание по поводу файлов конфигурации
В репозитории нет файла app/config/local.php. Его прототип лежит в app/config/local.example.php — там хранятся настройки подключения к базе данных и кэширования. Это сделано по двум причинам:
- Каждый разработчик/сервер имеет свои настройки
- Пароли не хранятся в репозитории
Есть еще один нюанс — app/config/params.php (будем использовать в следующей статье) подгружаем не сразу, а после инициализации приложения — это сделано для того, чтобы внутри него мы могли использовать компоненты приложения, такие как user.
Обзор скомпилированного конфига
config
Array ( [basePath] => /home/misha/bingo/app [import] => Array ( [0] => application.components.* [1] => application.models.* ) [preload] => Array ( [0] => log ) [components] => Array ( [log] => Array ( [class] => CLogRouter [routes] => Array ( [0] => Array ( [class] => CWebLogRoute [levels] => info, trace [except] => system.CModule.* [showInFireBug] => 1 [collapsedInFireBug] => 1 ) [1] => Array ( [class] => CProfileLogRoute [showInFireBug] => 1 ) ) ) [request] => Array ( [class] => Request [enableCsrfValidation] => 1 [csrfTokenName] => h ) [session] => Array ( [class] => CCacheHttpSession [sessionName] => s [cookieParams] => Array ( [httponly] => 1 ) ) [urlManager] => Array ( [urlFormat] => path [useStrictParsing] => 1 [showScriptName] => 1 [rules] => Array ( [] => site/index ) ) [db] => Array ( [connectionString] => mysql:host=127.0.0.1;dbname=test [username] => root [password] => [enableParamLogging] => 1 [enableProfiling] => 1 ) [cache] => Array ( [class] => CMemCache ) ) )
basePath — путь к папке приложения, по которому будет создан алиас пути «application».
import — список алиасов и путей, которые будут использоваться автозагрузчиком классов. По данным маскам мы подключаем папки app/components и app/models.
preload — компоненты, которые надо инициализировать сразу. Иначе компонент будет инициализирован при первом обращении (lazy load).
components — собственно, самый ужас для начинающих, давайте разбираться. :)
Компоненты
log — логирование (с) к.о. В режиме dev собираем логи по категориям info и trace (за исключением вызовов system.CModule, чтобы не плодить component xxx loaded ...) в консоль браузера, а так же логи по профайлингам. В режиме продакшн пишутся логи ошибок и предупреждений в app/runtime/application.log (по умолчанию для CFileLogRoute).
request — компонент request, включаем защиту от csrf и ожидаем хэш по ключу «h» для POST/PUT/DELETE запросов. Класс переопределен на Request — он выполняет дополнительные манипуляции над входящими данными. Обратите внимание, если бы мы не подключили папку «application.components.*» в импорте, то в данном поле «class» пришлось бы писать «application.components.Request».
session — сессии. Используем класс CCacheHttpSession для хранения сессий в кэше, в нашем случае — memcache. Если вы используете несколько компонентов кэширования, скажем cache и cache2, и хотите хранить сессии в cache2 — используйте настройку cacheID (к слову, такая настройка есть у всех компонентов, которые так или иначе используют кэш). Так же мы указали, что сессии должны быть в режиме HttpOnly.
urlManager — ака роутер. Используем формат «path» для роутинга в виде /foo/bar. Параметр «useStrictParsing» говорит, что следует использовать правила только из поля «rules», иначе попробует загрузить пару controller/action для запрошенного пути. «showScriptName» — я использую значение IN_DEV, которое подставилось в единичку, чтобы во время разработки генератор ссылок (о нем в следующей части) добавлял index.php перед созданными ссылками — "/index.php/controller/action?foo=bar" вместо '/controller/action?foo=bar". И последнее поле, «rules» — ничего заоблачного, все великолепно описано в документации.
db — компоненты для работы с базой данных. Параметры «enableParamLogging» и «enableProfiling» подставились из конфига dev.php, то есть в режиме продакшн эти настройки использоваться не будут, а наоборот, добавится кэширование схемы баз для увеличения производительности.
cache — кэширование. Используем старый добрый надежный memcache. Внимание! Пользователи комплекса open-server иногда могут наблюдать ошибки вроде «Memcache pool ...», если не указано поле «servers» для кэширования через адаптер «memcache». Это можно исправить. Замените «localhost» на «127.0.0.1» в framework/caching/CMemCache:101
Немного о компонентах в целом
Хотел бы добавить, что по сути все компоненты Yii — это объекты определенного класса, а все настройки — зачастую его свойства.
Внимательней читайте документацию, все замечательно и понятно расписано.
Разработка в IDE
Для корректной работы в IDE файл «framework/yiilite.php» следует помечать как текстовый, либо игнорировать.
Так же я всегда ингорирую, либо исключаю папки «framework/cli», «framework/gii», «framework/vendors», «framework/web/js/sources». Иначе возможны проблемы с автокомплитом php/js.
To be continued..
Пока что все, надеюсь кому-то эта статья будет полезной. В следующей части расскажу о нескольких виджетах, моделях и кэшировании.
До встречи.