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. Следует обратить внимание на индекс кода ошибки.

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

Оставьте комментарий