Для работы со штатным ORM нужно заводить модель для каждой таблицы. Всегда. Она может быть вообще пустой, но она должна быть. Ну, необязательно совсем пустой, там могут быть описания связей и всё такое.
Но всё выше сказанное не означает, что больше в моделях писать нечего. Ниже я попытаюсь систематизировать, что ещё такого можно, и даже стоит написать именно в модели.
1. Перечень полей
=========================
В модели обязательно должны быть описаны все поля таблицы. Подробнее проблема описана тут
Это должно выглядеть примерно так:
1 2 3 4 5 6 7 8 | 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, но лучше сделать для этого метод в модели. Даже если там будет всего одна строчка, поверьте, читаемость и писаемость лёгкость написания заметно увеличится!
Пример такой функции:
1 2 3 4 5 | public function published_only() { $this-> where('is_draft', '=', '0'); return $this; } |
и всё. В следующий раз вам не стоит париться и вспоминать какие поля и чему там они должны быть равны. Вам останется только логика приложения.
3. Характерное для этой таблицы представление данных
===============================
Иногда в базе данных удобно хранить одно, но показывать удобно другое. Примеры? Пожалуйста!
Храним в базе данных таймштамп, а порой нужно отображать отдельно дату и отдельно время:
1 2 3 4 5 6 | public function get_date(){ return substr($this->date, 0, 10); } public function get_time(){ return trim(substr($this->date, 10)); } |
Или ещё вот, храним в базе данных длину в дюймах, но можем вывести её раздельно в футах и дюймах:
1 2 3 4 5 6 | function length_ft(){ return floor($this->length/12); } function length_in(){ return $this->length- floor($this->length/12)*12; } |
А вот ещё, xраним в базе данных полные имя и фамилию, а можем вывести фамилию и инициалы:
1 2 3 4 5 6 7 8 | 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. Нестандартная обработка данных
============================
Например, выполняется голосование. Пользователь сайта ткнул на оценку (сердечко, звёздочку), и теперь нужно пересчитать средний голос. Для этого очень удобно добавлять оценки прямо в таблицу того за что голосуют (посты, видео, фото и т.д.), а раз данные прямо в таблице – то давайте сделаем метод для их подновления:
1 2 3 4 5 6 | public function vote($mark){ $this->rate= ($this->rate_count*$this->rate_count + $mark) /($this->rate_count+1); $this->rate_count++; $this->save(); } |
Да мало ли что вообще можно сделать!
Нестандартная обработка при сохранении
============================
Если при сохранении записи кроме собственно сохранения производится ещё серия действий над данными, например заполнить их значениями по-умолчанию, то можно хакнуть save() запихнуть прямо туда все эти дела:
1 2 3 4 5 | public function save(){ if ($this->title=='') $this->title='Untitled'; parent::save(); } |
Единственное пожелание, если вам слишком понравилось туда всё пихать – то очень скоро ваш save() может превратиться в помойку. Старайтесь писать читабельно и, по-возможности, выносить код в отдельные методы.
Валидация
============================
Обязательно используйте валидацию! Обязательно используйте валидацию встроенную в ORM. Если привыкнете так делать, то это существенно продвинет ваш код. Правила и поля для валидации стоит прописывать прямо в модели, а проверять просто вызовом метода check(). Что-то на подобие этого:
1 2 3 4 5 6 7 | 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() по той же схеме. При этом удобно, чтобы ваш текст ошибки вписался в штатный массив ошибок. Например так:
1 2 3 4 | if(ваше_условие){ $this->_validate->error('Название_поля_с_ошибкой','Индекс_ошибки'); $result=false; } |
Понятно, что сам текст ошибки нужно прописать в /application/messages/validation.php. Следует обратить внимание на индекс кода ошибки.
Вместо резюме
============================
Описывая всё вышесказанное одним предложением , можно сказать так, что следует максимально отделять логику поведения данных от логики приложения. Зачем? Просто мелкие куски легче разжевать и проглотить. Удачи всем!
=)
Посты по теме:
RSS-подписка
Не стоит перегружать модель “чужой” логикой. Например:
“3. Характерное для этой таблицы представление данных” – ето логика отображения и ее можно делать в шаблоне представления, пускай таймштапм сидит себе в базе спокойно)), “Валидация” пускай екшны контроллера валидируют данных сразу после получения.
И вобще хочу сказать что перемещение логики из одных частей mvc в другие по сути не дает пользы. Тут надо как то стандартизировать правила и принципы размещения логики, чтобы другие разработчики могли легко ориентироваться в любом mvc-приложении.
А если этот таймштамп надо так преобразовывать в десятке шаблонов? Писать это десять раз?
@ altesack:
2altesack Если так думать, то можно вобще все из шаблонов убрать и написать только
<? echo $shablon; ?>
//Извините все остальное в модели
@ Василий из Украины:
Я так себе представляю, что шаблоны специально выделены, чтобы дать возможность подключить дизайнера. Он-то точно скажет спасибо, если убрать всю логику из шаблона
Ну а если пишешь один – то вообще не принципиально. На вкус и цвет.
altesack пишет:
Я не понял о чем ты?
@ Василий из Украины:
Думаю стандарты нужны, когда работаешь в команде.
Когда ты работаешь один – ты сам себе стандарт.
И тут лучшее решение то, которое тебе удобно.
@ Василий из Украины:
Почитайте “Fat Stupid Ugly Controllers”, как по мне так там правильно расписано. Вы слишком буквально подходите к концепции MVC, что на данный момент и пример, вы трактуете совершенно не правильно.
Altesack пишет:
Соглашусь. Работая в команде лучше дать больше власти шаблонам, так ка в команде не далеко не все программисты. (ето я на работе уже проверил и ето не мои мысли а опыт)
Nejji пишет:
Вы хотите чтобы я накидал вам ссылок на книги которые я прочитал?))) Ваша критика какая то абстрактная, типа : “вы ничего не понимаете ибо ето неправильно”.
Давайте небудем спорить потому что ето бесполезно.
[...] Kohana 3.0. Мысли о том как надо писать модели. [...]
Кохана – отличный фреймворк. Жаль мало ресурсов по нему, по сравнению с тем же КИ.
Вот еще один ресурсик http://kohanaframework.su/
на котором будет даже переведенная на русский документация (начало уже есть).