Kohana 3.0. Мысли о том как надо писать модели.


Дык, модели бывают разные. И говорят, что сиськи способствуют популярности блогов :)
Для работы со штатным ORM нужно заводить модель для каждой таблицы. Всегда. Она может быть вообще пустой, но она должна быть. Ну, необязательно совсем пустой, там могут быть описания связей и всё такое.

Но всё выше сказанное не означает, что больше в моделях писать нечего. Ниже я попытаюсь систематизировать, что ещё такого можно, и даже стоит написать именно в модели.

1. Перечень полей
=========================
В модели обязательно должны быть описаны все поля таблицы. Подробнее проблема описана тут

Это должно выглядеть примерно так:

protected $_table_columns = array(
    'id'            =>  array('type'=>'int'),
    'title'          =>  array('type'=>'string'),
    'slug'          =>  array('type'=>'string'),
    'opened'            =>  array('type'=>'int'),
    'start_date'          =>  array('type'=>'date'),
    'end_date'          =>  array('type'=>'date')
    );

Понятно, что в каждом случае набор полей может отличаться.
Если структура полей ещё будет меняться — наверное не стоит торопится с этим списком.

2. Характерные для этой таблицы фильтры
=========================
Представьте себе что периодически нужно делать одну и ту же проверку для записей этой таблицы. Можно, конечно, каждый раз писать новое where, но лучше сделать для этого метод в модели. Даже если там будет всего одна строчка, поверьте, читаемость и писаемость лёгкость написания заметно увеличится!

Пример такой функции:

public function published_only()
{
    $this-> where('is_draft', '=', '0');
    return $this;
}

и всё. В следующий раз вам не стоит париться и вспоминать какие поля и чему там они должны быть равны. Вам останется только логика приложения.

3. Характерное для этой таблицы представление данных
===============================
Иногда в базе данных удобно хранить одно, но показывать удобно другое. Примеры? Пожалуйста!
Храним в базе данных таймштамп, а порой нужно отображать отдельно дату и отдельно время:

public function get_date(){
    return substr($this->date, 0, 10);
}
public function get_time(){
    return trim(substr($this->date, 10));
}

Или ещё вот, храним в базе данных длину в дюймах, но можем вывести её раздельно в футах и дюймах:

function length_ft(){
    return floor($this->length/12);
}
function length_in(){
    return $this->length- floor($this->length/12)*12;
}

А вот ещё, xраним в базе данных полные имя и фамилию, а можем вывести фамилию и инициалы:

function get_name(){
return    $this->get("name")
        ?
    $this->first_name." ".$this->last_name
        :
    $this->first_name." ".substr($this->last_name,0,1).
          ($this->last_name?".":"");
}

И таких примеров можно придумать много. Кто-то наверное подумает, что не стоит заводить функцию на пару строк, и лучше каждый раз писать этот код. Чтож, каждый решает для себя.

4. Нестандартная обработка данных
============================
Например, выполняется голосование. Пользователь сайта ткнул на оценку (сердечко, звёздочку), и теперь нужно пересчитать средний голос. Для этого очень удобно добавлять оценки прямо в таблицу того за что голосуют (посты, видео, фото и т.д.), а раз данные прямо в таблице — то давайте сделаем метод для их подновления:

public function vote($mark){
    $this->rate= ($this->rate_count*$this->rate_count + $mark)
                    /($this->rate_count+1);
    $this->rate_count++;
    $this->save();
}

Да мало ли что вообще можно сделать!

Нестандартная обработка при сохранении
============================
Если при сохранении записи кроме собственно сохранения производится ещё серия действий над данными, например заполнить их значениями по-умолчанию, то можно хакнуть save() запихнуть прямо туда все эти дела:

public function save(){
    if ($this->title=='')
       $this->title='Untitled';
    parent::save();
}

Единственное пожелание, если вам слишком понравилось туда всё пихать — то очень скоро ваш save() может превратиться в помойку. Старайтесь писать читабельно и, по-возможности, выносить код в отдельные методы.

Валидация
============================
Обязательно используйте валидацию! Обязательно используйте валидацию встроенную в ORM. Если привыкнете так делать, то это существенно продвинет ваш код. Правила и поля для валидации стоит прописывать прямо в модели, а проверять просто вызовом метода check(). Что-то на подобие этого:

                
if ($my_model->check() {
  $my_model->save();
}else{
  $data['errors']= $my_model->validate()->errors("");
  $data['data']= $my_model;
  $this->template->content = new View("editform", $data);
}

Если у вас есть своя хитрая проверка при сохранении, которая не вписывается по каким-нибудь причинам в логику штатных средств валидации — стоит впихнуть их туда силой.

Например можно сделать хак метода check() по той же схеме. При этом удобно, чтобы ваш текст ошибки вписался в штатный массив ошибок. Например так:

if(ваше_условие){
     $this->_validate->error('Название_поля_с_ошибкой','Индекс_ошибки');
     $result=false;
}

Понятно, что сам текст ошибки нужно прописать в /application/messages/validation.php. Следует обратить внимание на индекс кода ошибки.

Вместо резюме
============================
Описывая всё вышесказанное одним предложением , можно сказать так, что следует максимально отделять логику поведения данных от логики приложения. Зачем? Просто мелкие куски легче разжевать и проглотить. Удачи всем!
=)

Kohana 3.0. Мысли о том как надо писать модели.: 10 комментариев

  1. Василий из Украины

    Не стоит перегружать модель «чужой» логикой. Например:
    «3. Характерное для этой таблицы представление данных» — ето логика отображения и ее можно делать в шаблоне представления, пускай таймштапм сидит себе в базе спокойно)), «Валидация» пускай екшны контроллера валидируют данных сразу после получения.
    И вобще хочу сказать что перемещение логики из одных частей mvc в другие по сути не дает пользы. Тут надо как то стандартизировать правила и принципы размещения логики, чтобы другие разработчики могли легко ориентироваться в любом mvc-приложении.

  2. altesack Автор записи

    А если этот таймштамп надо так преобразовывать в десятке шаблонов? Писать это десять раз?

  3. Василий из Украины

    @ altesack:
    2altesack Если так думать, то можно вобще все из шаблонов убрать и написать только
    <? echo $shablon; ?>
    //Извините все остальное в модели

  4. altesack Автор записи

    @ Василий из Украины:
    Я так себе представляю, что шаблоны специально выделены, чтобы дать возможность подключить дизайнера. Он-то точно скажет спасибо, если убрать всю логику из шаблона :)

    Ну а если пишешь один — то вообще не принципиально. На вкус и цвет.

  5. Василий из Украины

    altesack пишет:

    @ Василий из Украины:
    Ну а если пишешь один – то вообще не принципиально. На вкус и цвет.

    Я не понял о чем ты?

  6. Altesack

    @ Василий из Украины:
    Думаю стандарты нужны, когда работаешь в команде.
    Когда ты работаешь один — ты сам себе стандарт.
    И тут лучшее решение то, которое тебе удобно.

  7. Nejji

    @ Василий из Украины:
    Почитайте «Fat Stupid Ugly Controllers», как по мне так там правильно расписано. Вы слишком буквально подходите к концепции MVC, что на данный момент и пример, вы трактуете совершенно не правильно.

  8. Василий из Украины

    Altesack пишет:

    @ Василий из Украины:
    Думаю стандарты нужны, когда работаешь в команде.
    Когда ты работаешь один – ты сам себе стандарт.
    И тут лучшее решение то, которое тебе удобно.

    Соглашусь. Работая в команде лучше дать больше власти шаблонам, так ка в команде не далеко не все программисты. (ето я на работе уже проверил и ето не мои мысли а опыт)

    Nejji пишет:

    @ Василий из Украины:
    Почитайте “Fat Stupid Ugly Controllers”, как по мне так там правильно расписано. Вы слишком буквально подходите к концепции MVC, что на данный момент и пример, вы трактуете совершенно не правильно.

    Вы хотите чтобы я накидал вам ссылок на книги которые я прочитал?))) Ваша критика какая то абстрактная, типа : «вы ничего не понимаете ибо ето неправильно».
    Давайте небудем спорить потому что ето бесполезно.

  9. Уведомление: Kohana 3: закладені статті | Блоґ Виспянського Ігоря

  10. Kohana_man

    Кохана — отличный фреймворк. Жаль мало ресурсов по нему, по сравнению с тем же КИ.
    Вот еще один ресурсик http://kohanaframework.su/
    на котором будет даже переведенная на русский документация (начало уже есть).

Комментарии запрещены.