Создание модуля на фреймворке Kohana
В этой статье хочу рассказать как создать свой модуль на фреймворке Kohana.
Что такое модуль, описывается тут
Немного теории
Сам фреймворк имеет 3 основные папки:
application — тут храниться ваш проект
modules — тут модули
system — тут ядро
Все названия папок и файлов, новых и старых, пишутся с маленькой буквы, желательно латинского алфавита, т.к. в методе Kohana::auto_load() все файлы приводятся к нижнему регистру. На это стоит обратить внимание, т.к. на ОС *unix это вылезет и будут потом куча вопросов, а чего у меня (под ОС Windows) работает, а тут нет!!!!! Насчет латиницы, ну тут особых ограничений нет, но принято всё писать латиницей!
Создания модуля
Заходим в папку modules и создаем необходимую нам папку.
Для того, чтобы это было наглядней создадим модуль для получения валюты из центробанка РФ на текущий день (украинского НБУ, не нашел api). Назовем папку модуля — currency (в названии папки можно использовать знак _).
modules
currency
Далее нужно создать простой класс, для какой-то работы, то просто в этой папке его и создаем, например класс назовем Test, значит файл будет называться test.php (расширение должно быть такое, какое описано в index-файле вашего проекта, константа define(‘EXT’, ‘.php’);)
Если же будите использовать MVC паттерн, то надо создать особую структуру папок.
classes -эта папка для классов контроллера и моделей
controller — если есть контроллер, то он храниться тут (назв Controller_Name, файл name.php)
model — тут модель, если есть (Model_Name, name.php)
config — хранятся всяческие настройки для модуля
views — шаблоны для отображения
vendor — библиотеки сторонних производителей
init.php — файл, инициализируемый при подключении модуля
Ессно, что всех этих папок может не быть, это структура папок, скажем по-умолчанию.
Как подключить модуль
Заходим в файл проекта — bootstrap.php и добавляем в описание модулей свой
Kohana::modules(array( 'auth' => MODPATH.'auth', // Basic authentication 'database' => MODPATH.'database', // Database access 'image' => MODPATH.'image', // Image manipulation 'orm' => MODPATH.'orm', // Object Relationship Mapping 'pagination' => MODPATH.'pagination', // Paging of results 'cache' => MODPATH.'cache', // Cache module 'currency' => MODPATH.'currency', // Подключения модуля получения валюты!!!!! ));
Загрузка модулей во фрейм будет в той последовательности, в которой они добавления в этот массив.
При загрузке сразу подключается файл init.php, если он есть, при инициализации модуля. Обычно в этом файле пишут роутер по которому будет доступна работа модуля, если такое требуется.
Переходим к практике
Структура папок описано, начнем писать.
Описываем файл инициализации init.php:
// Роутеры для работы с валютами Route::set('currency', 'getcurrency(/<date>)', array('date'=>'([0-9\/]+)')) ->defaults(array( 'controller' => 'currency', 'action' => 'index', 'date' => NULL, ) );
Далее описываем работу с контроллером Controller_Currency (currency.php):
class Controller_Currency extends Controller { /** * Получение данных по указанному дню * * @return void */ public function action_index() { $date = $this->request->param('date', date('d/m/Y')); $currency_model = new Model_Curr; $currency_data = $currency_model->get_currency_from_server($date); print_r($currency_data); } }// End Currency Controller
Описываем работу модели Model_Curr (curr.php):
class Model_Curr extends Model { /** * Получения данных с сервера ЦБРФ (http://www.cbr.ru/) * * @param string $date текущая дата * @return string */ public function get_currency_from_server($date) { $allow_currency = array('EUR', 'USD'); $link = "http://www.cbr.ru/scripts/XML_daily.asp?date_req=$date"; $text = @file_get_contents($link); $xml = new SimpleXMLElement($text); foreach ($xml->Valute as $curr) { if(in_array($curr->CharCode, $allow_currency)) { $currency[] = $date . ' ' . $curr->CharCode . ' ' . UTF8::str_ireplace(',', '.', (string)$curr->Value); } } return $currency; } } // End Currency Model
В итоге набираем в строке адреса вашего браузера ссылку http://yourprojectname/getcurrency/14/06/2010
и на экране получаем ответ:
Array ( [0] => 24/03/2012 USD 29.4038 [1] => 24/03/2012 EUR 38.8189 )
Демо тут
Данные по валюте получены. Модуль можно использовать в других проектах.
Подводные камни
При работе с модулями могут произойти некоторые проблемки.
1 Если имеется в проекте роутер с таким же урлом как в файле инициализации модуля, то роутер модуля будет замещен роутером проекта.
Для избегания, просто делаем другой роутер или ставим описание роутера проекта раньше чем описание загрузки модулей в файле bootstrap.php.
2 Если одинаковое название моделей, то модель будет вызвана из проекта, а не из модуля!!! Обойти эту проблему мне не удалось, т.к. само ядро ищет файл в проекте и если найдено поиск дальше не идет, а если нет, то ищется пока не будет найдено. Единственный выход — прописать другое название для модели.
UPD: Пересобрал модуль для версии Kohana 3.2, часть комментариев уже не валидны. Через время выложу на github.com
UPD2: Выложил всё на GitHub
Статья просмотренна 103384 раз, зашло посетителей 28493
А зачем писать
public $template = 'main';
public $auto_render = true;
и
$this->auto_render = FALSE;
если вы наследуете Controller?
Да, то лишнее… Верно заметили, только при наследовании от Kohana_Controller_Template нужны эти св-ва.
Я просто взял текст контроллера с других модулей и полностью не почистил. Работать будет все равно нормально, просто лишнее.
а зачем в модуле роут писать когда его можно просто как класс использовать?
Можно как класс, я писал модули которые как виджеты потом работали, вызывались как статик методы в некоторых местах шаблона.
А можно через ссылку, вот например капча в кохане сделана через ссылку /captcha/default и через статик метод класса
Да, да, сам 1000 раз в эту статью смотрел, всё никак не могу запомнить. Поправил, спасибо.
ЗЫ А вообще слово иностранное тут о его морфологи можно долго рассуждать.
что делает строка
UTF8::str_ireplace(',', '.', (string)$curr->Value)
?
если сменить просто на ((int)$curr->Value), то возвращаемый тип будет числом?
Привет Виталий. Дело в том, что сервер отдает значение в виде <Value>27,4570</Value>, где разделение дробной части от целой через символ ",". Если в дальнейшем делать арифметические действия, то результаты будут ошибочны.
Если сделать как Вы предлагаете, то php тупо выкинет дробную часть и покажет целую (округлять не будет).
Почему не чекаются нигде ошибки?!
Дата что приходит в контроллер, ну и ошибки от сервака где валюты парсим?!
Ну цель статьи было показать как строить модуль, а не создать рабочий с кучей фичь. Писалось все во время создание статьи)). Звиняйте…
Большое спасибо за статью, очень полезный материал при написании своего первого модуля на кохане 🙂
Будут вопросы — задавайте.
на сколько я помню в массивах последние элементы идут без запятой, а то пхп матюкаться будет…
'date' => NULL,
'currency' => MODPATH.'currency',
Не знаю какую версию пыха ты узаещь, в ветке 5.2.x я таких трабл не замечал. Ты думаешь я выложил не рабочий пример? Я же создавал, тестировал и описывал.
5.2 и 5.3 проблема есть
можно посмотреть архив модуля?
может я где ошибся.
Я переработаю модуль под текущую версию и вылажу на github
Доброго времени суток.
Попробовал Ваш пример.
Выдало ошибку — ErrorException [ Warning ]: Missing argument 1 for Controller_Currency::action_index()
MODPATH/currency/classes/controller/currency.php [ 10 ]
а в 10-той строке у меня
public function action_index($date)
В чем может быть глюк?
Дело было еще кажется под Kohana 3.0.* и там параметры передавались, как аргументы метода, да и как-то странно, в роутере, если дату не указывать и так будет NULL ('date' => NULL,), и проверка у меня там идет на дату… В общем спасибо за найденную ошибку!
Сейчас в ветке 3.2.* параметры передаются через метод $this->request->params('date'); более стало правильней.
Спасибо, по больше бы таких статей в и-нете.
Спаибо.
Пока не указал NULL
public function action_index($date=NULL)
Выдавал ошибку
https://github.com/maxnag/currency
Nothing to see here yet. Move along.
Added module to git, now u can see.
Здравствуйте!
Не подскажете, как возможно подключить файл стилей, который лежит в папке с модулем?
добрый день! ну подключить его напрямую не получится, т.к. по правильному папки с модулям, системной и самим сайтом не должно быть видно из браузера, т.е. эти папки лежать как бы за сайтом, а сайт видит только точку входа и соот папки которые лежат рядом с точкой входа.
Но подключить эти стили можно если написать класс, который будет проходить по всем указанным (опционально) модулям и забирать оттуда файлы стилей, и потом "выплёвывать их" в шаблон. По-дефолту такого функционала нет, поэтому либо делайте по-феншую либо пишите свою реализацию.
Да я так и понял, поэтому уже написал класс, который по аналогу модуля userguide ищет в папке media заданный стиль и отдает его через роут. Теперь могу подключать стили хоть в каждом модуле таким макаром <link rel="stylesheet" href="/media/css…. Аналогично с картинками и js.
Просто как-то не очень люблю статику через php подключать, а по-феншую для моей задумки не подходит((
P.S. мне не пришло на мыло, что Вы мне ответили, хотя подписывался на все комментарии. Баг?