Итак, мы скачали дистрибутив новой беты Kohana v3.0 и горим желанием создать новый супер-пупер-проект на ней. Впрочем, уже при первом взгляде на файлы дистрибутива становится понятно, что все будет не так просто. Вместо привычных нам папок controllers, models и т.д. мы видим непонятные classes и extensions. Почему-то в APPPATH появился файл bootstrap.php, который мы раньше видели в SYSPATH/core… В общем, давайте посмотрим, какие процессы происходят при работе новой версии фреймворка.
Для начала откроем фронтенд (файл index.php). Он сильно напоминает знакомый нам файл из ветки 2.3. Главные различия — в конце файла. Там мы видим новые подключаемые файлы:
// Load the base, low-level functions require SYSPATH.'base'.EXT; // Load the main Kohana class require SYSPATH.'classes/kohana'.EXT; // Bootstrap the application require APPPATH.'bootstrap'.EXT; |
Помимо упомянутого нами файла bootstrap.php подключаются скрипты base.php и classes/kohana.php. Первый содержит всего одну функцию __($string, array $values = NULL) для работы с i18n-ресурсами, второй по сути аналог класса Kohana_Core из core/kohana.php версии 2.3. Как и прежде, он отвечает за автозагрузку классов (метод auto_load()), работу с конфигами и т.д. Более подробно изменения в нем мы рассмотрим позже.
Итак, основные действия разворачиваются в файле bootstrap.php. Просматриваем его содержимое и обнаруживаем первые интересные строчки:
/** * Initialize Kohana, setting the default options. * * The following options are available: * - base_url: path, and optionally domain, of your application * - index_file: name of your index file, usually "index.php" * - charset: internal character set used for input and output * - profile: enable or disable internal profiling * - caching: enable or disable internal caching */ Kohana::init(array('charset' => 'utf-8', 'base_url' => '/ko3/')); |
Как мы помним, ранее класс Kohana инициализировался без каких-либо дополнительных параметров, все подгружалось из многочисленных конфигов (в том числе из главного — config.php). Теперь основные параметры прописаны в классе Kohana по умолчанию как свойства, а мы можем их поменять, передав в массиве в метод Kohana::init().
- profile — флаг, разрешающий или запрещающий профилирование (т.е. сохранение статистики выполнения задач фреймворка, например подгрузки модулей ядром, используется класс Profiler). По умолчанию свойство установлено в TRUE. В 2.3 статистика собиралась автоматически (с помощью класса Benchmark).
- caching — флаг включения кэширования внутренних путей (т.е. повторно файлы искаться не будут, пути сохраняются к кэше). По умолчанию FALSE. В версии 2.3 использовался параметр $config['internal_cache'] для этих же целей.
- charset — используемая кодировка. По умолчанию конечно же ‘utf-8‘. В 2.3 локаль выставлялась в юникод автоматически.
- base_url — аналог параметра $config['site_domain'] в 2.3. По умолчанию ‘/‘, однако обратите внимание, что в поставляемом файле bootstrap.php это значение переопределяется строкой ‘/ko3/‘.
- index_file — имя фронтенда, аналог $config['index_page']. Если вы используете .htaccess, можно этот параметр заменить на пустую строку.
Kohana::modules(array( // 'database' => MODPATH.'database', // Database access // 'image' => MODPATH.'image', // Image manipulation (not complete) // 'orm' => MODPATH.'orm', // Object Relationship Mapping (not complete) // 'pagination' => MODPATH.'pagination', // Paging of results (not complete) // 'paypal' => MODPATH.'paypal', // PayPal integration (not complete) // 'todoist' => MODPATH.'todoist', // Todoist integration )); |
Далее подгружаются модули, для этого был создан метод Kohana::modules(), принимающий их в виде массива ‘имя модуля‘ => ‘путь к модулю‘. Если переданный путь (абсолютный или относительный) не является директорией, модуль загружен не будет. Модули хранятся в переменной $_modules, а пути (т.к. в Kohana каскадная система, при изменении списка модулей пути тоже пересчитываются) — в $_paths. Пока что не вижу никаких способов добавить/удалить один конкретный модуль без передачи полного списка в метод modules(), что не очень удобно при попытке подключить модуль «на лету».
В текущей «бете» из модулей доступен лишь модуль Database с драйвером MySQL. Ядро максимально облегчено, так что ожидаем очередной виток сравнений производительности фреймворков Kohana и Yii при выводе ‘hello, world!‘.
/** * Attach the file write to logging. Any Kohana_Log object can be attached, * and multiple writers are supported. */ Kohana::$log->attach(new Kohana_Log_File(APPPATH.'logs')); |
Этот кусок кода отвечает за «прикручивание» логирования в папке APPPATH/logs/ с помощью метода attach(). Свойство Kohana::$log представляет собой объект Kohana_Log, управляющий записью в различные логи. В качестве ресурса для ведения логов создан абстрактный класс Kohana_Log_Writer, от которого должны наследоваться все создаваемые ресурсы. В поставке дистрибутива присутствует класс для работы с файловыми логами (Kohana_Log_File).
/** * Set the routes. Each route must have a minimum of a name, a URI and a set of * defaults for the URI. */ Route::set('default', '(<controller>(/<action>(/<id>)))') ->defaults(array( 'controller' => 'welcome', 'action' => 'index', 'id' => NULL)); |
Дальше добавляются настройки роутинга. Вместо конфиг-файлов routes.php предлагается добавлять маршруты через Route::set() и Route::defaults(). Первый метод добавляет в таблицу роутинга именованный маршрут (имя маршрута => URI), причем URI записан в несколько непривычной для нас форме: элементы-переменные маршрута заключены в угловые скобки, необязательные элементы сгруппированы в скобки. Так, в приведенном выше примере параметры action и id являются необязательными. Значения по умолчанию для используемых ключей устанавливаются методом Route::defaults().
Наверное вы обратили внимание на параметр action. Это по сути имя метода, но в дистрибутиве KO3 слово «метод» не используется, далее поймете почему.
/** * Execute the main request using PATH_INFO. If no URI source is specified, * the URI will be automatically detected. */ echo Request::instance($_SERVER['PATH_INFO']) ->execute() ->send_headers() ->response; |
Данным вызовом выполняется обработка текущего URI (вычисление контроллера и экшена), собственно выполнение и вывод результата. Дело в том, что вместо класса Router (как это было в 2.3), анализ введенного URL и создание/выполнение нужного метода контроллера производит класс Request (это уже не маленький хэлпер request, как раньше). Метод execute() вычисляет имя контроллера и экшена и инициирует их выполнение. По сравнению с 2.3 есть определенные нюансы:
-
Имена контроллеров начинаются с префикса ‘Controller_‘ (в 2.3 используется суффикс ‘_Controller‘).
-
Знаки подчеркивания в имени контроллера преобразовываются в слэши, т.е. ‘Controller_Test_Me‘ будет ассоциирован с файлом /classes/controller/test/me.php.
-
Конструктор контроллера на входе принимает экземпляр класса Request.
-
Имена методов определяются с помощью префикса ‘action_‘ (отсюда название action для параметров Route). Например, http://localhost/welcome/index будет обращаться к контроллеру Controller_Welcome, метод action_index().
-
До вызова экшена выполняется метод before(), а после — метод after(). Таким образом, в контроллере можно выполнять какие-то действия, которые не будут выполнены в его потомках (как если бы мы использовали конструктор/деструктор).
Метод Request::send_headers() наверное покажется знакомым (в 2.3 есть событие ‘system.send_headers‘), он отсылает HTTP-ответ и прочие заголовки.
А что хранится в свойстве Request->response? Это собственно результат работы контроллера. Придется привыкнуть, что все наши представления необходимо «вкладывать» в эту переменную, например как $this->request->response = new View(‘index’);.
Итоги
- На данный момент фреймворк практически голый, не хватает множества привычных модулей и библиотек (например, ORM и Pagination).
- Расположение папок и файлов поменялось. Теперь все библиотеки, хэлперы, модели и контроллеры лежат в папке classes. Причем контроллеры и модели в папках controller и model соответственно, а вот библиотеки и хэлперы в корне (чем они теперь отличаются, я пока не могу понять, разве что регистром слов в названии класса).
- Имена классов тоже поменялись, но не все. Если библиотеки продолжают называться именами типа Session_Core, а хэлперы — arr_core, то контроллеры и модели начинаются с префиксов ‘controller_‘ и ‘model_‘ соответственно.
- Хуков и событий я не увидел ВООБЩЕ. Даже не знаю, что и думать, возможно удастся обойтись упомянутыми ранее методами before() и after() контроллеров?
- Конфиги тоже сильно поменялись. Например, так теперь выглядит конфигурационный файл с настройками подключения к базе данных MySQL (возможно, он неполный, т.к. нет информации о необходимых параметрах, все на основе анализа исходников):
// Файл APPPATH/config/database.php return array( 'default' => array ( 'persistent' => FALSE, 'type' => 'mysql', 'username' => 'user', 'password' => 'password', 'hostname' => 'host', 'database' => 'dbname', 'charset' => 'utf8', ) );
- Есть подозрения, что ORM будет создан с нуля (сейчас его вообще нет), а не портирован с 2.4. Соответственно, будут новые баги, глюки и просьбы о помощи…
- Кэширование в виде отдельной библиотеки отсутствует, есть метод Kohana::cache() для работы с файловым кэшем (причем складироваться файлы кэша будут жестко в APPPATH/cache/).
- Напоследок — самое «вкусное»: никакой документации (кроме исходников), вся доступная помощь скорее всего может быть получена только в IRC-канале #kohana. Да и вместо привычных «тикетов» в dev.kohanaphp.com придется обращаться на github.com.
В общем, если нет желания поучаствовать в создании перспективной ветки Коханы, оставайтесь на 2.3, в крайнем случае тестируйте 2.4 (там хоть изменения не настолько коренные). А романтики без претензий на комфортную работу — присоединяйтесь, будем помогать.
UPDATE. Изменения в архитектуре фреймворка, связанные с появлением библиотеки Request, предоставили возможность сколько угодно раз выполнять различные методы контроллеров без лишних http-запросов. Т.е. обычный вызов Request::factory($url)->execute() вернет результат выполнения метода X контроллера Y, вычисленных на основе анализа URL, указанного в переменной $url. По сути, получаем готовый HMVC уже в каркасе фреймворка.
Мммм, даже не знаю, что и сказать.
Что-то мне это не нравится. Без хуков, это вообще грустно. Event’ов получается нет?
Единственное: Request::factory($url)->execute() нравится.
Только вернулся к Kohana, решил небольшой сайтик написать, думаю всетаки буду на 2.3.4 писать.
Я подозреваю, что события и хуки будут доступны в виде отдельного модуля (скорее всего их кто-нибудь по-быстрому портирует в KO3).
А поддержка HMVC уже на уровне ядра не может не радовать
Я вот лично жду ORM и Cache (особенно для Database)
У меня кстати есть несколько оч интересных идеек по поводу того, что в принципе можно добавить в кохану, чтобы удобней было работать.
Неее, события и хуки они ж ядро и составляли. В бутстрапе как все делалось: евенты заносились, вешались на них действия и все поочередно работало, а тут если их нет изначально то и вряд ли будет (:
пс: дай свой jabber/icq ?:)
Да, я помню, схема была удобная и гибкая. Видимо в погоне за быстрыми секундами решили из ядра все это выкинуть.
Теперь вместо system.ready придется использовать before() или конструктор базового контроллера. А вот с событиями приложения можно запросто разобраться, внедрив модуль Events, тут ИМХО ничего сложного. Например, я чаще использовал именно события приложения. А ядро пусть будет легким, не всем же нужны события или базы данных
Even with google translator, this post was a good read. Thanks! See you around the forum
@jleft
Кстати, также перед загрузкой модуля есть возможность выполнить какие-то настройки, для этого система проверяет модуль на наличие скрипта init.php, и выполняет его если находит.