Jelly. Реализация собственных типов данных полей

В своем предыдущем посте я уже начал рассказывать о работе во фреймворке Kohana с такой ORM, как Jelly. Теперь попробую осветить такой момент, как создание собственных типов данных полей на примере обычного DatePicker'а из JQuery UI.

Теги: ORM Kohana jqueryui Jelly

Рассмотрим все ту же таблицу новостей, о которой я рассказывал ранее. У каждой из новостей есть такое поле, как дата публикации. Допустим по функциональности реализовываемого сайта нам необходимо самостоятельно (вручную) задавать дату публикации новостей. Для такой цели нам и подойдет стандартный DatePicker из библиотеки JQuery UI.

Итак, приступим. Для начала определимся от какого из стандартных классов типов полей данных в Jelly мы бы могли унаследоваться для реализации задуманного. Назовем создаваемый нами класс типа данных полей Field_Date, при выводе которого в представлении будет выводится поле с подключенным к нему DatePicker'ом, и унаследуем его от Field_String (в представлении обычный текстовый input, к которому и должен цепляться DatePicker).

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

структура модуля jelly-datepicker

Мы будем придерживаться такой же структуры, которая реализована в самой Jelly.

Нашей задачей по сути является переопределение метода input() у Field_Date, который и занимается выводом отображения поля в представление. Создадим в папке classes/jelly/field файл date.php со следующим содержанием:

<?php defined('SYSPATH') or die('No direct script access.');
 
abstract class Jelly_Field_Date extends Jelly_Field_String
{
 
public function input($prefix = 'jelly/field', $data = array())
{
static $has_added = FALSE;
 
// Get the view name
$view = $this->_input_view($prefix);
 
// Grant acces to all of the vars plus the field object
$data = array_merge(get_object_vars($this), $data, array('field' => $this));
 
// Make sure there is an 'attrs' array set to prevent error in view
$data['attributes'] = Arr::get($data, 'attributes', array());
 
$data['has_added'] = $has_added;
 
$result = View::factory($view, $data);
 
$has_added = TRUE;
 
// By default, a view object only needs a few defaults to display it properly
return $result;
}
}

Данный метод input() отличается от стандартного (определенного у Jelly_Field) тем, что мы создаем внутри метода статическую переменную, которая должна будет помнить добавлено ли уже на страницу поле с типом Field_Date или еще нет. Далее будет понятно, для чего это нам нужно.

Теперь согласно структуре модуля Jelly нам нужно создать файл date.php в папке classes/field с содержанием:

<?php defined('SYSPATH') or die('No direct script access.');
 
class Field_Date extends Jelly_Field_Date
{
 
}

Теперь нам осталось создать представление для данного типа поля данных. В папке views/jelly/field создадим файл date.php:

<? if ( ! $has_added): ?>	
<link type="text/css" href="/media/css/ui-lightness/jquery-ui-1.8.2.custom.css" rel="stylesheet" />
<script src="/media/js/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="/media/js/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script>
<script src="/media/js/i18n/jquery.ui.datepicker-ru.js" type="text/javascript"></script>
<? endif ?>
<script type="text/javascript">
$(function(){
$.datepicker.setDefaults(
$.extend($.datepicker.regional["ru"])
);
$("#<?= 'field-' . $name ?>").datepicker();
});
</script>
<?= Form::input($name, $value, $attributes + array('id' => 'field-'.$name)) ?>

И видим, что подключение всех необходимых файлов Java Script происходит в зависимости от переменной $has_added. То есть если хотя бы раз на данную страницу было выведено поле с типом данных Field_Date, то больше подключение скриптов происходить не будет. Далее идет привязка DatePicker'а к полю формы input, а затем вывод этого поля.

В итоге у нас получается следующая структура:

окончательная структура jelly-datepicker

Последним действием перед использованием созданного поля остается прописать подключение данного модуля в bootstrap.php:

Kohana::modules(array(
'auth' => MODPATH.'auth', // Basic authentication
// 'cache' => MODPATH.'cache', // Caching with multiple backends
// 'codebench' => MODPATH.'codebench', // Benchmarking tool
'database' => MODPATH.'database', // Database access
// 'image' => MODPATH.'image', // Image manipulation
// 'orm' => MODPATH.'orm', // Object Relationship Mapping
// 'pagination' => MODPATH.'pagination', // Paging of results
// 'userguide' => MODPATH.'userguide', // User guide and API documentation
'jelly' => MODPATH.'jelly',
'jelly-datepicker' => MODPATH.'jelly-datepicker'
));

Не забудьте, что сам модуль Jelly тоже должен быть подключен.